Django表單

使用表單

假設你想從表單接收用戶名數據,通常狀況下,你須要在HTML中手動編寫一個以下的表單元素:html

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

-name/和HTTP方法POST。form元素內部還定義了一個說明標籤<label>和一個發送按鈕‘submit’,以及最關鍵的接收用戶輸入的<input>元素。前端

1、編寫表單類

咱們能夠經過Django提供的Form類來自用生成上面的表單,再也不須要手動在HTML中編寫。python

首先,在你當前app內新建一個forms.py文件(這個套路是Django的慣用手法,就像views.pymodels.py等等),而後輸入下面的內容:django

from django import forms

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

要點:bootstrap

  • 提早導入forms模塊
  • 全部的表單類都要繼承forms.Form類
  • 每一個表單字段都有本身的字段類型好比CharField,它們分別對應一種HTML語言中的<form>元素中的表單元素。這一點和Django模型系統的設計很是類似。
  • 例子中的label用於設置說明標籤
  • max_length限制最大長度爲100。它同時起到兩個做用,一是在瀏覽器頁面限制用戶輸入不可超過100個字符,二是在後端服務器驗證用戶輸入的長度不可超過100。

(警告:因爲瀏覽器頁面是能夠被篡改、僞造、禁用、跳過的,全部的HTML手段的數據驗證只能防止意外不能防止惡意行爲,是沒有安全保證的,破壞分子徹底能夠跳過瀏覽器的防護手段僞造發送請求!因此,在服務器後端,必須將前端當作「裸機」來對待,再次進行徹底完全的數據驗證和安全防禦!)後端

每一個Django表單的實例都有一個內置的is_valid()方法,用來驗證接收的數據是否合法。若是全部數據都合法,那麼該方法將返回True,並將全部的表單數據轉存到它的一個叫作cleaned_data的屬性中,該屬性是以個字典類型數據。瀏覽器

當咱們將上面的表單渲染成真正的HTML元素,其內容以下:安全

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

必定要注意,它不包含服務器

標籤自己以及提交按鈕!!!爲何要這樣?方便你本身控制表單動做和CSS,JS以及其它相似bootstrap框架的嵌入!

2、視圖處理

須要在視圖中,實例化咱們編寫好的表單類。app

# views.py

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

from .forms import NameForm

def get_name(request):
    # 若是form經過POST方法發送數據
    if request.method == 'POST':
        # 接受request.POST參數構造form類的實例
        form = NameForm(request.POST)
        # 驗證數據是否合法
        if form.is_valid():
            # 處理form.cleaned_data中的數據
            # ...
            # 重定向到一個新的URL
            return HttpResponseRedirect('/thanks/')

    # 若是是經過GET方法請求數據,返回一個空的表單
    else:
        form = NameForm()

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

要點是:

  • 對於GET方法請求頁面時,返回空的表單,讓用戶能夠填入數據;
  • 對於POST方法,接收表單數據,並驗證;
  • 若是數據合法,按照正常業務邏輯繼續執行下去;
  • 若是不合法,返回一個包含先前數據的表單給前端頁面,方便用戶修改。

經過表單的is_bound屬性能夠獲知一個表單已經綁定了數據,仍是一個空表。

3、模板處理

在Django的模板中,咱們只須要按下面處理,就能夠獲得完整的HTML頁面:

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

要點:

  • <form>...</form>標籤要本身寫;
  • 使用POST的方法時,必須添加{% csrf_token %}標籤,用於處理csrf安全機制;
  • {{ form }}表明Django爲你生成其它全部的form標籤元素,也就是咱們上面作的事情;
  • 提交按鈕須要手動添加!

提示:默認狀況下,Django支持HTML5的表單驗證功能,好比郵箱地址驗證、必填項目驗證等等。

4、高級技巧

上面的例子中,只有一個用戶名輸入框,太簡單了,實際上有更多的表單元素。看下面的例子:

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField(widget=forms.Textarea)
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)

這個例子就有4個框組了。實際上Django的表單模塊爲咱們內置了許多表單字段,以下所示:

  • BooleanField
  • CharField
  • ChoiceField
  • TypedChoiceField
  • DateField
  • DateTimeField
  • DecimalField
  • DurationField
  • EmailField
  • FileField
  • FilePathField
  • FloatField
  • ImageField
  • IntegerField
  • GenericIPAddressField
  • MultipleChoiceField
  • TypedMultipleChoiceField
  • NullBooleanField
  • RegexField
  • SlugField
  • TimeField
  • URLField
  • UUIDField
  • ComboField
  • MultiValueField
  • SplitDateTimeField
  • ModelChoiceField
  • ModelMultipleChoiceField

每個表單字段類型都對應一種Widget類,每一種Widget類都對應了HMTL語言中的一種input元素類型,好比<input type="text">。須要在HTML中實際使用什麼類型的input,就須要在Django的表單字段中選擇相應的field。好比要一個<input type="text">,能夠選擇一個CharField

一旦你的表單接收數據並驗證經過了,那麼就能夠從form.cleaned_data字典中讀取全部的表單數據,下面是一個例子:

# views.py

from django.core.mail import send_mail

if form.is_valid():
    subject = form.cleaned_data['subject']
    message = form.cleaned_data['message']
    sender = form.cleaned_data['sender']
    cc_myself = form.cleaned_data['cc_myself']

    recipients = ['info@example.com']
    if cc_myself:
        recipients.append(sender)

    send_mail(subject, message, sender, recipients)
    return HttpResponseRedirect('/thanks/')

5、 使用表單模板

1.表單渲染格式

前面咱們經過{{ form }}模板語言,簡單地將表單渲染到HTML頁面中了,實際上,有更多的方式:

  • {{ form.as_table }} 將表單渲染成一個表格元素,每一個輸入框做爲一個<tr>標籤
  • {{ form.as_p }} 將表單的每一個輸入框包裹在一個<p>標籤內 tags
  • {{ form.as_ul }} 將表單渲染成一個列表元素,每一個輸入框做爲一個<li>標籤

注意:你要本身手動編寫<table><ul>標籤。

下面是將上面的ContactForm做爲{{ form.as_p }}的例子:

<p><label for="id_subject">Subject:</label>
    <input id="id_subject" type="text" name="subject" maxlength="100" required /></p>
<p><label for="id_message">Message:</label>
    <textarea name="message" id="id_message" required></textarea></p>
<p><label for="id_sender">Sender:</label>
    <input type="email" name="sender" id="id_sender" required /></p>
<p><label for="id_cc_myself">Cc myself:</label>
    <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>

注意:Django自動爲每一個input元素設置了一個id名稱,對應label的for參數。

2.手動渲染表單字段

直接{{ form }}雖然好,啥都不用操心,可是每每並非你想要的,好比你要使用CSS和JS,好比你要引入Bootstarps框架,這些都須要對錶單內的input元素進行額外控制,那怎麼辦呢?手動渲染字段就能夠了。

能夠經過{{ form.name_of_field }}獲取每個字段,而後分別渲染,以下例所示:

{{ form.non_field_errors }}
<div class="fieldWrapper">
    {{ form.subject.errors }}
    <label for="{{ form.subject.id_for_label }}">Email subject:</label>
    {{ form.subject }}
</div>
<div class="fieldWrapper">
    {{ form.message.errors }}
    <label for="{{ form.message.id_for_label }}">Your message:</label>
    {{ form.message }}
</div>
<div class="fieldWrapper">
    {{ form.sender.errors }}
    <label for="{{ form.sender.id_for_label }}">Your email address:</label>
    {{ form.sender }}
</div>
<div class="fieldWrapper">
    {{ form.cc_myself.errors }}
    <label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
    {{ form.cc_myself }}
</div>

其中的label標籤甚至能夠用label_tag()方法來生成,因而能夠簡寫成下面的樣子:

<div class="fieldWrapper">
    {{ form.subject.errors }}
    {{ form.subject.label_tag }}
    {{ form.subject }}
</div>

這樣子是否是更加靈活了呢?可是靈活的代價就是咱們要寫更多的代碼,又偏向原生的HTML代碼多了一點。

3. 渲染表單錯誤信息:

注意上面的例子中,咱們使用{{ form.name_of_field.errors }}模板語法,在表單裏處理錯誤信息。對於每個表單字段的錯誤,它其實會實際生成一個無序列表,參考下面的樣子:

<ul class="errorlist">
    <li>Sender is required.</li>
</ul>

這個列表有個默認的CSS樣式類errorlist,若是你想進一步定製這個樣式,能夠循環錯誤列表裏的內容,而後單獨設置樣式:

{% if form.subject.errors %}
    <ol>
    {% for error in form.subject.errors %}
        <li><strong>{{ error|escape }}</strong></li>
    {% endfor %}
    </ol>
{% endif %}

一切非字段的錯誤信息,好比表單的錯誤,隱藏字段的錯誤都保存在{{ form.non_field_errors }}中,上面的例子,咱們把它放在了表單的外圍上面,它將被按下面的HTML和CSS格式渲染:

4. 循環表單的字段:

若是你的表單字段有相同格式的HMTL表現,那麼徹底能夠循環生成,沒必要要手動的編寫每一個字段,減小冗餘和重複代碼,只須要使用模板語言中的{% for %}循環,以下所示:

{% for field in form %}
    <div class="fieldWrapper">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
        {% if field.help_text %}
        <p class="help">{{ field.help_text|safe }}</p>
        {% endif %}
    </div>
{% endfor %}

下表是{{ field }}中很是有用的屬性,這些都是Django內置的模板語言給咱們提供的方便:

屬性 說明
{{ field.label }} 字段對應的label信息
{{ field.label_tag }} 自動生成字段的label標籤,注意與{{ field.label }}的區別。
{{ field.id_for_label }} 自定義字段標籤的id
{{ field.value }} 當前字段的值,好比一個Email字段的值someone@example.com
{{ field.html_name }} 指定字段生成的input標籤中name屬性的值
{{ field.help_text }} 字段的幫助信息
{{ field.errors }} 包含錯誤信息的元素
{{ field.is_hidden }} 用於判斷當前字段是否爲隱藏的字段,若是是,返回True
{{ field.field }} 返回字段的參數列表。例如{{ char_field.field.max_length }}

5. 不可見字段的特殊處理:

不少時候,咱們的表單中會有一些隱藏的不可見的字段,好比honeypot。咱們須要讓它在任什麼時候候都彷彿不存在通常,好比有錯誤的時候,若是你在頁面上顯示了不可見字段的錯誤信息,那麼用戶會很迷惑,這是哪來的呢?因此,一般咱們是不顯示不可見字段的錯誤信息的。

Django提供了兩種獨立的方法,用於循環那些不可見的和可見的字段,hidden_fields()visible_fields()。這裏,咱們能夠稍微修改一下前面的例子:

{# 循環那些不可見的字段 #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# 循環可見的字段 #}
{% for field in form.visible_fields %}
    <div class="fieldWrapper">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
    </div>
{% endfor %}
相關文章
相關標籤/搜索