Django4.0 使用表單-構(gòu)建一張表單

2022-03-16 17:58 更新

假設(shè)您希望在您的網(wǎng)站上創(chuàng)建一張簡易的表單,用來獲取用戶的名字。您需要在模板中使用類似代碼:

<form action="/your-name/" method="post">
    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name" value="{{ current_name }}">
    <input type="submit" value="OK">
</form>

這告訴瀏覽器將表單數(shù)據(jù)返回給URL ?/your-name/? ,并使用 ?POST ?方法。它將顯示一個標(biāo)簽為 "Your name:" 的文本字段,以及一個 "OK" 按鈕。如果模板上下文包含一個 ?current_name ?變量,它會被預(yù)填充到 ?your_name ?字段。
您需要一個視圖來渲染這個包含HTML表單的模板,并能適當(dāng)提供 ?current_name ?字段。
提交表單時,發(fā)送給服務(wù)器的 POST 請求將包含表單數(shù)據(jù)。
現(xiàn)在,您還需要一個與該 ?/your-name/? URL相對應(yīng)的視圖,該視圖將在請求中找到相應(yīng)的鍵/值對,然后對其進(jìn)行處理。
這是一張非常簡單的表單。實(shí)際應(yīng)用中,一張表單可能包含數(shù)十上百的字段,其中許多可能需要預(yù)填充,并且我們可能希望用戶在結(jié)束操作前需要多次來回編輯-提交。
我們可能需要在瀏覽器中進(jìn)行一些驗(yàn)證,甚至在表單提交之前;我們可能希望使用更復(fù)雜的字段 ,以允許用戶做類似日期選擇等操作。
此刻,我們很容易通過使用Django來完成以上大部分工作。

Form類

我們已經(jīng)很清楚想要的HTML表單看起來會是什么樣子。首先,在Django中這樣做:

from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='Your name', max_length=100)

它定義了一個只包含一個字段( ?your_name ?)的 ?Form ?類。我們已經(jīng)為這個字段提供了友好的標(biāo)簽,當(dāng)它渲染后會顯示在 ?<label>? 中(在這種情況下,如果我們省略之前指定的 label ,它還是會自動生成一個一樣的標(biāo)簽)。
字段的最大長度由 ?max_length ?來定義。它做了兩件事情。首先它在HTML的 ?<input>? 上增加了 ?maxlength="100"? (這樣瀏覽器會在第一時間阻止用戶輸入超過這個數(shù)量的字符串)。其次它還會在Django收到瀏覽器傳過來的表單時,對數(shù)據(jù)長度進(jìn)行驗(yàn)證(也就是服務(wù)器端驗(yàn)證)。

Form 實(shí)例有一個 ?is_valid()? 方法,該方法對其所有字段運(yùn)行驗(yàn)證例程。 調(diào)用此方法時,如果所有字段都包含有效數(shù)據(jù),它將:

  • 返回 ?True?
  • 將表單的數(shù)據(jù)放到它的屬性 ?cleaned_data ?中

這樣整個表單在第一次渲染時,會顯示如下:

<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100" required>

視圖

發(fā)回Django網(wǎng)站的表單數(shù)據(jù)由視圖來處理,一般和發(fā)布這個表單用的是同一個視圖。這允許我們重用一些相同的邏輯。

為了處理表單,我們需要將它實(shí)例化到我們希望發(fā)布的URL的對應(yīng)的視圖中:

from django.http import HttpResponseRedirect
from django.shortcuts import render

from .forms import NameForm

def get_name(request):
    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = NameForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:
            return HttpResponseRedirect('/thanks/')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = NameForm()

    return render(request, 'name.html', {'form': form})

如果我們訪問這個視圖用的是 ?GET ?請求,它會創(chuàng)建一個空的表單實(shí)例并將其放置在模板上下文中進(jìn)行渲染。這是我們在首次訪問這個URL時能預(yù)料到會發(fā)生的情況。
如果表單提交用的是 ?POST ?請求,那么該視圖將再次創(chuàng)建一個表單實(shí)例并使用請求中的數(shù)據(jù)填充它: ?form = NameForm(request.POST) ?,這叫“綁定數(shù)據(jù)到表單” (現(xiàn)在它是一張 綁定的 表單)。
我們調(diào)用表單的 ?is_valid()? 方法;如果不為 ?True ?,我們帶著表單返回到模板。這次表單不再為空( 未綁定 ),所以HTML表單將用之前提交的數(shù)據(jù)進(jìn)行填充,放到可以根據(jù)需要進(jìn)行編輯和修正的位置。
如果 ?is_valid()? 為 ?True ?,我們就能在其 ?cleaned_data ?屬性中找到所有通過驗(yàn)證的表單數(shù)據(jù)。我們可以在發(fā)送一個HTTP重定向告訴瀏覽器下一步去向之前用這些數(shù)據(jù)更新數(shù)據(jù)庫或者做其他處理。

模板

我們沒有必要在模板 ?name.html? 中做過多的操作:

<form action="/your-name/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit">
</form>

所有的表單字段及其屬性都將通過Django模板語言從 ?{{ form }} ?中被解包成HTML標(biāo)記。

表格和跨站請求偽造保護(hù)

Django自帶一個簡單易用的 跨站請求偽造防護(hù) 。當(dāng)通過 POST 方法提交一張啟用了CSRF防護(hù)的表單時,您必須使用上例中這樣的模板標(biāo)簽 ?csrf_token ?。但是,由于CSRF防護(hù)在模板中沒有與表單直接綁定,因此這個標(biāo)簽在本頁文檔之后的示例中都將被忽略。

HTML5輸入類型和瀏覽器驗(yàn)證

如果您的表單包含 ?URLField ?, ?EmailField ?或者其他整數(shù)字段類型,Django將使用 url , email 和 number HTML5輸入類型。默認(rèn)情況下,瀏覽器可能會在這些字段上應(yīng)用他們自己的驗(yàn)證,這也許比Django的驗(yàn)證更加嚴(yán)格。如果您想禁用這個行為,請在 form 標(biāo)簽上設(shè)置 ?novalidate ?屬性,或者在字段上指定一個不同的控件,比如 ?TextInput ?

現(xiàn)在我們有了一個可以工作的web表單,它通過一張Django ?Form ?描述,由一個視圖來處理并渲染成一個HTML ?<form>? 。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號