Django – Form có sẵn của Django

5/5 - (7 votes)

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><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.

Untitled

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><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><input> trong thẻ cặp thẻ <tr></tr>
  • form.as_p: bọc các thẻ <label><input> trong cặp thẻ <p></p>
  • form.as_ul: bọc các thẻ <label><input> trong cặp thẻ <li>

Tuy nhiên bạn phải khai báo cặp thẻ <table></table><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>

Untitled

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.

Untitled

Đây là giao diện được thiết kế lại dùng thẻ <table> rất đơn giản.

Untitled

4.5 4 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Inline Feedbacks
View all comments
Quyền Nguyễn
Quyền Nguyễn
3 năm trước

Hi, mình có một số thắc mắc, bạn giúp mình với:

  1. Trong form.py, mình tạo một vài form class chứa một số filed nào đó. Các form class này được gọi trong view.py. Mình có thể gọi một form class từ nhiều view khác nhau hay không, nó có ảnh hưởng hiệu suất hay gì không?
  2. Mình có 100 form class khác nhau, vậy làm sao để tối ưu nó cho tốt. Tức mà mình phải tạo 100 form class và mỗi form class chứa 5 fields hoặc tạo vài form class và sẽ sử dụng lại các field này.
Trương Minh Trí
Trương Minh Trí
1 năm trước

các link mở rộng dẫn sang bài khác của a hỏng hết r , a sửa lại thành collape frame trong bài này luôn cho tiện theo dõi đi a