Trong bài Form và các View có sẵn chúng ta đã tạo form bằng các thẻ HTML, nếu việc code các form bằng tay như thế mệt mỏi quá thì Django cung cấp cho chúng ta lớp Form
để chúng ta có thể tạo form ngay từ code Python và có thể nhận request và trả response về cho người dùng.
Trong HTML thì form là một tập các thẻ element nằm giữa cặp thẻ <form>...</form>
cho phép người dùng thực hiện một công việc nào đó, sau đó gửi dữ liệu lên server rồi trả về câu trả lời. Hầu hết HTML chỉ hỗ trợ các thẻ element cơ bản như text, checkbox… muốn hiển thị các element cao cấp hơn như DateTimePicker
(chọn ngày tháng), Slider
(thanh trượt)… bạn phải dùng đến các ngôn ngữ hỗ trợ thêm khác như Javascript, CSS…
Hoặc bạn có thể dùng lớp Form
có sẵn của Django, Django cung cấp lớp Form
hỗ trợ tạo form một cách nhanh chóng và dễ dàng. Trong phần này chúng ta sẽ tạo form đăng ký user đơn giản sử dụng lớp Form
do Django cung cấp.
Tạo app
Đầu tiên chúng ta tạo một app mới với tên là user_auth
:
C:\Project\mysite>python manage.py startapp user_auth
Tiếp theo chúng ta khai báo app này trong list INSTALLED_APP:
... INSTALLED_APPS = [ 'user_auth', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] ...
Tạo Form
Trong thư mục user-auth
chúng ta tạo một file mới với tên là forms.py
để lưu các lớp form.
from django import forms class RegisterForm(forms.Form): username = forms.CharField(label='Username', max_length=100) password = forms.CharField(widget=forms.PasswordInput) email = forms.EmailField(label='Email')
Các lớp dùng để tạo form được kế thừa từ lớp django.forms.Form
.
username = forms.CharField(label='Username', max_length=100) password = forms.CharField(widget=forms.PasswordInput) email = forms.EmailField(label='Email')
Bên trong lớp này chúng ta cũng khai báo các trường là các đối tượng Field
, nhưng các đối tượng Field
này không giống như Field
khi tạo model, Field
ở đây là để tạo form HTML còn field bên model là để tạo bảng CSDL (hơi rối :()
Mỗi loại lớp Field
nhận vào vài tham số khi khởi tạo nhưng không có tham số nào là bắt buộc phải có, chẳng hạn như label
của CharField
sẽ được dùng cho thuộc tính name
trong thẻ <label>...
Ở trên chúng ta có 2 CharField
dùng để nhập text và một EmailField
dùng để nhập email. Đây là danh sách các lớp và tham số của form Field của Django.
password = forms.CharField(widget=forms.PasswordInput)
Vì HTML có nhiều thẻ element có công dụng chung nhưng lại hiển thị dữ liệu khác nhau, chẳng hạn như một thẻ <input>
có thể dùng để nhập tên, số điện thoại, password… do đó Django cung cấp cho mỗi đối tượng Field
một đối tượng Widget
để chúng ta có thể chỉ định loại text nào hiển thị cái gì.
Ở trên chúng ta dùng CharField
để hiển thị password bằng cách truyền tham số widget là forms.PasswordInput.
Đây là danh sách các lớp Widget.
Tạo Template
Chúng ta tạo một thư mục với tên là templates,
trong thư mục này chúng ta lại tạo một thư mục khác là user_auth
rồi tạo một file HTML với tên là register.html:
<form action="" method="post"> {% csrf_token %} {{ form }} <input type="submit" value="Submit" /> </form>
Khi chúng ta viết các lớp form, Django sẽ nhìn các trường mà chúng ta khai báo rồi sinh ra các thẻ <input>
tương ứng, ngoại trừ cặp thẻ <form>...</form>
và thẻ <input type="submit"/>
<form action="" method="post">
Thuộc tính action
sẽ chuyển dữ liệu tới đường dẫn tương ứng, ở đây mình để trống tức là gửi lại cho chính trang đó. Phương thức POST
sẽ mã hóa dữ liệu được gửi đi.
{{ form }}
Chúng ta có thể tham chiếu đến phần tử form
trong list context mà chúng ta sẽ khai báo trong các hàm view bên dưới, và Django sẽ tự động tạo các thẻ <label>
và <input>
cho chúng ta.
Tạo View
Chúng ta viết hàm view register()
như sau.
from django.shortcuts import render # Create your views here. from django.http import HttpResponse from .forms import RegisterForm def register(request): if request.method == 'POST': response = HttpResponse() response.write("<h1>Thanks for registering</h1></br>") response.write("Your username: " + request.POST['username'] + "</br>") response.write("Your email: " + request.POST['email'] + "</br>") return response registerForm = RegisterForm() return render(request, 'user_auth/register.html', {'form':registerForm})
Đoạn code trên rất đơn giản, chúng ta chỉ import lớp RegisterForm
từ module forms.py
mà chúng ta viết ở trên. Sau đó tạo một đối tượng RegisterForm
rồi đưa vào làm phần tử của list context (tham số thứ 3 trong hàm render()).
if request.method == 'POST': response = HttpResponse() response.write("<h1>Thanks for registering</h1></br>") response.write("Your username: " + request.POST['username'] + "</br>") response.write("Your email: " + request.POST['email'] + "</br>") return response
Sau khi người dùng đã nhập các thông tin cần thiết vào các ô text và bấm gửi thì dữ liệu sẽ gửi trả lại hàm register()
do chúng ta đã thiết lập nó trong thuộc tính action
ở file template. Nên ở đây chúng ta kiểm tra xem nếu phương thức gửi tới là phương thức POST
thì trả về câu trả lời với thông tin mà người dùng đã nhập
Tiếp theo chúng ta tạo url
tới hàm view này, đầu tiên chúng ta khai báo một module urls.py
của riêng app user_auth
đã:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^register$', views.register), ]
Sau đó là khai báo url của project tới app user_auth.
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^user-auth/', include('user_auth.urls')), ]
Bây giờ bạn có thể chạy server và trỏ đường dẫn tới localhost:8000/user-auth/register/ để xem giao diện mặc định do Form
của Django tạo ra.
Như bạn thấy trong hình trên giao diện do Django tạo ra mặc định nhìn rất “chuối” vì nhiệm vụ của Django chỉ là tự sinh code cho 2 thẻ element là <label>
và <input>
cho chúng ta rảnh tay hơn mà thôi, bản thân Django cũng cung cấp một số thiết lập để chúng ta tùy chỉnh giao diện nhưng rất hạn chế. Phần lớn chúng ta sẽ phải tự chỉnh bằng tay bằng cách sửa đối code trong file template, thêm các file CSS, JS… để giao diện nhìn đẹp hơn.
Có một số tùy chọn hiển thị mà Django cung cấp cho chúng ta là:
form.as_table:
bọc các thẻ<label>
và<input>
trong thẻ cặp thẻ<tr></tr>
form.as_p:
bọc các thẻ<label>
và<input>
trong cặp thẻ<p></p>
form.as_ul:
bọc các thẻ<label>
và<input>
trong cặp thẻ<li>
Tuy nhiên bạn phải khai báo cặp thẻ <table></table>
và <ul></ul>
tương ứng trước khi dùng. Ví dụ:
<form action="" method="post"> {% csrf_token %} <table> {{ form.as_table }} </table> <input type="submit" value="Submit" /> </form>
Giao diện nhìn có đỡ hơn một tí 🙂
Hoặc nếu muốn bạn có thể truy xuất từng phần tử của biến form trong file template để hiển thị theo ý muốn:
<form action="" method="post"> {% csrf_token %} <table> <tr> <th> <label for="{{ form.username.id_for_label }}">User:</label> </th> <td> {{ form.username }} <td> </tr> <tr> <th> <label for="{{ form.password.id_for_label }}">Password:</label> </th> <td> {{ form.password }} </td> </tr> <tr> <th> <label for="{{ form.email.id_for_label }}">Email:</label> </th> <td> {{ form.email }} </td> </tr> <tr> <td></td> <td> <input type="submit" value="Submit"> </td> </tr> </table> </form>
Bạn chỉ cần lấy theo cú pháp form.<tên thuộc tính>
là Django sẽ tự động sinh code cho các thẻ tương ứng. Ví dụ như form.username...
Ngoài ra bạn còn có thể lấy các thuộc tính field nữa. Trong ví dụ trên là form.username.id_for_label
sẽ lấy về id được tạo ra tự động. Đây là danh sách các thuộc tính field có trong Django.
Đây là giao diện được thiết kế lại dùng thẻ <table>
rất đơn giản.