About this documenthtml
This document provides an introduction to Django’s form handling features. For a more detailed look at specific areas of the forms API, see The Forms API, Form fields, and Form and field validation.python
django.forms is Django’s form-handling library.django
While it is possible to process form submissions just using Django’s HttpRequest class, using the form library takes care of a number of common form-related tasks. Using it, you can:api
The library deals with these concepts:app
The library is decoupled from the other Django components, such as the database layer, views and templates. It relies only on Django settings, a couple of django.utils helper functions and Django’s internationalization hooks (but you’re not required to be using internationalization features to use this library).ide
A Form object encapsulates a sequence of form fields and a collection of validation rules that must be fulfilled in order for the form to be accepted. Form classes are created as subclasses of django.forms.Form and make use of a declarative style that you’ll be familiar with if you’ve used Django’s database models.oop
★Form包含了fields和校驗的規則, 編寫Form必須繼承 django.forms.Form, 而後聲明式地定義你的數據,這和定義Django db models是相似的。post
For example, consider a form used to implement 「contact me」 functionality on a personal Web site:ui
from django import forms class ContactForm(forms.Form): subject = forms.CharField(max_length=100) message = forms.CharField() sender = forms.EmailField() cc_myself = forms.BooleanField(required=False)
A form is composed of Field objects. In this case, our form has four fields: subject, message, sender andcc_myself. CharField, EmailField and BooleanField are just three of the available field types; a full list can be found in Form fields.this
If your form is going to be used to directly add or edit a Django model, you can use a ModelForm to avoid duplicating your model description.
★若是form在django的model基礎上添加和編輯field,能夠使用 ModelForm 避免重複勞動。
The standard pattern for processing a form in a view looks like this:
from django.shortcuts import render from django.http import HttpResponseRedirect def contact(request): if request.method == 'POST': # If the form has been submitted... form = ContactForm(request.POST) # A form bound to the POST data if form.is_valid(): # All validation rules pass # Process the data in form.cleaned_data # ... return HttpResponseRedirect('/thanks/') # Redirect after POST else: form = ContactForm() # An unbound form return render(request, 'contact.html', { 'form': form, })
★以上演示如何在view裏使用定義好的form
There are three possible code paths here:
Form submitted? | Data? | What occurs |
---|---|---|
Unsubmitted | None yet | Template gets passed unbound instance of ContactForm. |
Submitted | Invalid data | Template gets passed bound instance of ContactForm. |
Submitted | Valid data | Valid data is processed. Redirect to a 「thanks」 page. |
The distinction between Bound and unbound forms is important:
★講了form的兩種狀態:未綁定和綁定
To see how to handle file uploads with your form, see Binding uploaded files to a form.
★用form上傳文件,有特殊的規則
Once is_valid() returns True, the successfully validated form data will be in the form.cleaned_data dictionary. This data will have been converted nicely into Python types for you.
★當 form 驗證合格(is_valid() == True)時,用 form.cleaned_data 字典來取得數據。
Note
You can still access the unvalidated data directly from request.POST at this point, but the validated data is better.
In the above example, cc_myself will be a boolean value. Likewise, fields such as IntegerField andFloatField convert values to a Python int and float respectively.
Read-only fields are not available in form.cleaned_data (and setting a value in a custom clean() method won’t have any effect). These fields are displayed as text rather than as input elements, and thus are not posted back to the server.
Extending the earlier example, here’s how the form data could be processed:
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) from django.core.mail import send_mail send_mail(subject, message, sender, recipients) return HttpResponseRedirect('/thanks/') # Redirect after POST
★這是使用form.cleaned_data字典來取得數據的例子。
Tip
For more on sending email from Django, see Sending email.
Forms are designed to work with the Django template language. In the above example, we passed ourContactForm instance to the template using the context variable form. Here’s a simple example template:
<form action="/contact/" method="post">{% csrf_token %} {{ form.as_p }} <input type="submit" value="Submit" /> </form>
The form only outputs its own fields; it is up to you to provide the surrounding <form> tags and the submit button.
If your form includes uploaded files, be sure to include enctype="multipart/form-data" in the formelement. If you wish to write a generic template that will work whether or not the form has files, you can use the is_multipart() attribute on the form:
<form action="/contact/" method="post" {% if form.is_multipart %}enctype="multipart/form-data"{% endif %}>
★無論上傳的是否是文件類型使用 is_multipart() 來聲明。
Forms and Cross Site Request Forgery protection
Django ships with an easy-to-use protection against Cross Site Request Forgeries. When submitting a form via POST with CSRF protection enabled you must use the csrf_token template tag as in the preceding example. However, since CSRF protection is not directly tied to forms in templates, this tag is omitted from the following examples in this document.
form.as_p will output the form with each form field and accompanying label wrapped in a paragraph. Here’s the output for our example template:
<form action="/contact/" method="post"> <p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p> <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p> <p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p> <p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p> <input type="submit" value="Submit" /> </form>
Note that each form field has an ID attribute set to id_<field-name>, which is referenced by the accompanying label tag. This is important for ensuring forms are accessible to assistive technology such as screen reader software. You can also customize the way in which labels and ids are generated.
★生成的form field有默認的ID爲 id_<field-name> , 也能夠定製ID的樣式。
You can also use form.as_table to output table rows (you’ll need to provide your own <table> tags) andform.as_ul to output list items.
If the default generated HTML is not to your taste, you can completely customize the way a form is presented using the Django template language. Extending the above example:
<form action="/contact/" method="post"> {{ form.non_field_errors }} <div class="fieldWrapper"> {{ form.subject.errors }} <label for="id_subject">Email subject:</label> {{ form.subject }} </div> <div class="fieldWrapper"> {{ form.message.errors }} <label for="id_message">Your message:</label> {{ form.message }} </div> <div class="fieldWrapper"> {{ form.sender.errors }} <label for="id_sender">Your email address:</label> {{ form.sender }} </div> <div class="fieldWrapper"> {{ form.cc_myself.errors }} <label for="id_cc_myself">CC yourself?</label> {{ form.cc_myself }} </div> <p><input type="submit" value="Send message" /></p> </form>
★若是不滿意默認生成的HTML,能夠在用Django 模板語言定製生成的HTML。
Each named form-field can be output to the template using {{ form.name_of_field }}, which will produce the HTML needed to display the form widget. Using {{ form.name_of_field.errors }} displays a list of form errors, rendered as an unordered list. This might look like:
<ul class="errorlist"> <li>Sender is required.</li> </ul>
The list has a CSS class of errorlist to allow you to style its appearance. If you wish to further customize the display of errors you can do so by looping over them:
{% if form.subject.errors %} <ol> {% for error in form.subject.errors %} <li><strong>{{ error|escape }}</strong></li> {% endfor %} </ol> {% endif %}
★循環輸出errors能夠定製如何顯示錯誤信息。
If you’re using the same HTML for each of your form fields, you can reduce duplicate code by looping through each field in turn using a {% for %} loop:
<form action="/contact/" method="post"> {% for field in form %} <div class="fieldWrapper"> {{ field.errors }} {{ field.label_tag }}: {{ field }} </div> {% endfor %} <p><input type="submit" value="Send message" /></p> </form>
★在這個循環裏,{{ field }}是BoundField 的實例。如下是一些field的屬性,它們很是有用。
Within this loop, {{ field }} is an instance of BoundField. BoundField also has the following attributes, which can be useful in your templates:
This attribute is True if the form field is a hidden field and False otherwise. It’s not particularly useful as a template variable, but could be useful in conditional tests such as:
{% if field.is_hidden %}
{# Do something special #}
{% endif %}
If your site uses the same rendering logic for forms in multiple places, you can reduce duplication by saving the form’s loop in a standalone template and using the include tag to reuse it in other templates:
<form action="/contact/" method="post"> {% include "form_snippet.html" %} <p><input type="submit" value="Send message" /></p> </form> # In form_snippet.html: {% for field in form %} <div class="fieldWrapper"> {{ field.errors }} {{ field.label_tag }}: {{ field }} </div> {% endfor %}
★把form的循環放在獨立的模板內,而後用 include 標籤能夠重用相同的渲染邏輯。
If the form object passed to a template has a different name within the context, you can alias it using thewith argument of the include tag:
<form action="/comments/add/" method="post"> {% include "form_snippet.html" with form=comment_form %} <p><input type="submit" value="Submit comment" /></p> </form>
★在 include 語句中使用用 with 參數能夠重命名。
If you find yourself doing this often, you might consider creating a custom inclusion tag.