Working with forms¶
About this document
This document provides an introduction to the basics of web forms and howthey are handled in Django. For a more detailed look at specific areas ofthe forms API, seeThe Forms API,Form fields, andForm and field validation.
Unless you’re planning to build websites and applications that do nothing butpublish content, and don’t accept input from your visitors, you’re going toneed to understand and use forms.
Django provides a range of tools and libraries to help you build forms toaccept input from site visitors, and then process and respond to the input.
HTML forms¶
In HTML, a form is a collection of elements inside<form>...</form> thatallow a visitor to do things like enter text, select options, manipulateobjects or controls, and so on, and then send that information back to theserver.
Some of these form interface elements - text input or checkboxes - are fairlysimple and are built into HTML itself. Others are much more complex; aninterface that pops up a date picker or allows you to move a slider ormanipulate controls will typically use JavaScript and CSS as well as HTML form<input> elements to achieve these effects.
As well as its<input> elements, a form must specify two things:
- where: the URL to which the data corresponding to the user’s input shouldbe returned
- how: the HTTP method the data should be returned by
As an example, the login form for the Django admin contains several<input> elements: one oftype="text" for the username, one oftype="password" for the password, and one oftype="submit" for the“Log in” button. It also contains some hidden text fields that the userdoesn’t see, which Django uses to determine what to do next.
It also tells the browser that the form data should be sent to the URLspecified in the<form>’saction attribute -/admin/ - and that itshould be sent using the HTTP mechanism specified by themethod attribute -post.
When the<inputtype="submit"value="Login"> element is triggered, thedata is returned to/admin/.
GET andPOST¶
GET andPOST are the only HTTP methods to use when dealing with forms.
Django’s login form is returned using thePOST method, in which the browserbundles up the form data, encodes it for transmission, sends it to the server,and then receives back its response.
GET, by contrast, bundles the submitted data into a string, and uses thisto compose a URL. The URL contains the address where the data must be sent, aswell as the data keys and values. You can see this in action if you do a searchin the Django documentation, which will produce a URL of the formhttps://docs.djangoproject.com/search/?q=forms&release=1.
GET andPOST are typically used for different purposes.
Any request that could be used to change the state of the system - for example,a request that makes changes in the database - should usePOST.GETshould be used only for requests that do not affect the state of the system.
GET would also be unsuitable for a password form, because the passwordwould appear in the URL, and thus, also in browser history and server logs,all in plain text. Neither would it be suitable for large quantities of data,or for binary data, such as an image. A Web application that usesGETrequests for admin forms is a security risk: it can be easy for an attacker tomimic a form’s request to gain access to sensitive parts of the system.POST, coupled with other protections like Django’sCSRF protection offers more control over access.
On the other hand,GET is suitable for things like a web search form,because the URLs that represent aGET request can easily be bookmarked,shared, or resubmitted.
Django’s role in forms¶
Handling forms is a complex business. Consider Django’s admin, where numerousitems of data of several different types may need to be prepared for display ina form, rendered as HTML, edited using a convenient interface, returned to theserver, validated and cleaned up, and then saved or passed on for furtherprocessing.
Django’s form functionality can simplify and automate vast portions of thiswork, and can also do it more securely than most programmers would be able todo in code they wrote themselves.
Django handles three distinct parts of the work involved in forms:
- preparing and restructuring data to make it ready for rendering
- creating HTML forms for the data
- receiving and processing submitted forms and data from the client
It ispossible to write code that does all of this manually, but Django cantake care of it all for you.
Forms in Django¶
We’ve described HTML forms briefly, but an HTML<form> is just one part ofthe machinery required.
In the context of a Web application, ‘form’ might refer to that HTML<form>, or to the DjangoForm that produces it, or to thestructured data returned when it is submitted, or to the end-to-end workingcollection of these parts.
The DjangoForm class¶
At the heart of this system of components is Django’sForm class. Inmuch the same way that a Django model describes the logical structure of anobject, its behavior, and the way its parts are represented to us, aForm class describes a form and determines how it works and appears.
In a similar way that a model class’s fields map to database fields, a formclass’s fields map to HTML form<input> elements. (AModelFormmaps a model class’s fields to HTML form<input> elements via aForm; this is what the Django admin is based upon.)
A form’s fields are themselves classes; they manage form data and performvalidation when a form is submitted. ADateField and aFileField handle very different kinds of data and have to dodifferent things with it.
A form field is represented to a user in the browser as an HTML “widget” - apiece of user interface machinery. Each field type has an appropriate defaultWidget class, but these can be overridden asrequired.
Instantiating, processing, and rendering forms¶
When rendering an object in Django, we generally:
- get hold of it in the view (fetch it from the database, for example)
- pass it to the template context
- expand it to HTML markup using template variables
Rendering a form in a template involves nearly the same work as rendering anyother kind of object, but there are some key differences.
In the case of a model instance that contained no data, it would rarely if everbe useful to do anything with it in a template. On the other hand, it makesperfect sense to render an unpopulated form - that’s what we do when we wantthe user to populate it.
So when we handle a model instance in a view, we typically retrieve it from thedatabase. When we’re dealing with a form we typically instantiate it in theview.
When we instantiate a form, we can opt to leave it empty or pre-populate it, forexample with:
- data from a saved model instance (as in the case of admin forms for editing)
- data that we have collated from other sources
- data received from a previous HTML form submission
The last of these cases is the most interesting, because it’s what makes itpossible for users not just to read a website, but to send information backto it too.
Building a form¶
The work that needs to be done¶
Suppose you want to create a simple form on your website, in order to obtainthe user’s name. You’d need something like this in your template:
<formaction="/your-name/"method="post"><labelfor="your_name">Your name:</label><inputid="your_name"type="text"name="your_name"value="{{current_name}}"><inputtype="submit"value="OK"></form>
This tells the browser to return the form data to the URL/your-name/, usingthePOST method. It will display a text field, labeled “Your name:”, and abutton marked “OK”. If the template context contains acurrent_namevariable, that will be used to pre-fill theyour_name field.
You’ll need a view that renders the template containing the HTML form, andthat can supply thecurrent_name field as appropriate.
When the form is submitted, thePOST request which is sent to the serverwill contain the form data.
Now you’ll also need a view corresponding to that/your-name/ URL which willfind the appropriate key/value pairs in the request, and then process them.
This is a very simple form. In practice, a form might contain dozens orhundreds of fields, many of which might need to be pre-populated, and we mightexpect the user to work through the edit-submit cycle several times beforeconcluding the operation.
We might require some validation to occur in the browser, even before the formis submitted; we might want to use much more complex fields, that allow theuser to do things like pick dates from a calendar and so on.
At this point it’s much easier to get Django to do most of this work for us.
Building a form in Django¶
TheForm class¶
We already know what we want our HTML form to look like. Our starting point forit in Django is this:
fromdjangoimportformsclassNameForm(forms.Form):your_name=forms.CharField(label='Your name',max_length=100)
This defines aForm class with a single field (your_name). We’veapplied a human-friendly label to the field, which will appear in the<label> when it’s rendered (although in this case, thelabelwe specified is actually the same one that would be generated automatically ifwe had omitted it).
The field’s maximum allowable length is defined bymax_length. This does two things. It puts amaxlength="100" on the HTML<input> (so the browser should prevent theuser from entering more than that number of characters in the first place). Italso means that when Django receives the form back from the browser, it willvalidate the length of the data.
AForm instance has anis_valid() method, which runsvalidation routines for all its fields. When this method is called, if allfields contain valid data, it will:
- return
True - place the form’s data in its
cleaned_dataattribute.
The whole form, when rendered for the first time, will look like:
<labelfor="your_name">Your name:</label><inputid="your_name"type="text"name="your_name"maxlength="100"required/>
Note that itdoes not include the<form> tags, or a submit button.We’ll have to provide those ourselves in the template.
The view¶
Form data sent back to a Django website is processed by a view, generally thesame view which published the form. This allows us to reuse some of the samelogic.
To handle the form we need to instantiate it in the view for the URL where wewant it to be published:
fromdjango.shortcutsimportrenderfromdjango.httpimportHttpResponseRedirectfrom.formsimportNameFormdefget_name(request):# if this is a POST request we need to process the form dataifrequest.method=='POST':# create a form instance and populate it with data from the request:form=NameForm(request.POST)# check whether it's valid:ifform.is_valid():# process the data in form.cleaned_data as required# ...# redirect to a new URL:returnHttpResponseRedirect('/thanks/')# if a GET (or any other method) we'll create a blank formelse:form=NameForm()returnrender(request,'name.html',{'form':form})
If we arrive at this view with aGET request, it will create an empty forminstance and place it in the template context to be rendered. This is what wecan expect to happen the first time we visit the URL.
If the form is submitted using aPOST request, the view will once againcreate a form instance and populate it with data from the request:form=NameForm(request.POST) This is called “binding data to the form” (it is nowabound form).
We call the form’sis_valid() method; if it’s notTrue, we go back tothe template with the form. This time the form is no longer empty (unbound)so the HTML form will be populated with the data previously submitted, where itcan be edited and corrected as required.
Ifis_valid() isTrue, we’ll now be able to find all the validated formdata in itscleaned_data attribute. We can use this data to update thedatabase or do other processing before sending an HTTP redirect to the browsertelling it where to go next.
The template¶
We don’t need to do much in ourname.html template. The simplest exampleis:
<formaction="/your-name/"method="post">{%csrf_token%}{{form}}<inputtype="submit"value="Submit"/></form>
All the form’s fields and their attributes will be unpacked into HTML markupfrom that{{form}} by Django’s template language.
Forms and Cross Site Request Forgery protection
Django ships with an easy-to-useprotection against Cross Site RequestForgeries. When submitting a form viaPOST withCSRF protection enabled you must use thecsrf_token template tagas in the preceding example. However, since CSRF protection is notdirectly tied to forms in templates, this tag is omitted from thefollowing examples in this document.
HTML5 input types and browser validation
If your form includes aURLField, anEmailField or any integer field type, Django willuse theurl,email andnumber HTML5 input types. By default,browsers may apply their own validation on these fields, which may bestricter than Django’s validation. If you would like to disable thisbehavior, set thenovalidate attribute on theform tag, or specifya different widget on the field, likeTextInput.
We now have a working web form, described by a DjangoForm, processedby a view, and rendered as an HTML<form>.
That’s all you need to get started, but the forms framework puts a lot more atyour fingertips. Once you understand the basics of the process described above,you should be prepared to understand other features of the forms system andready to learn a bit more about the underlying machinery.
More about DjangoForm classes¶
All form classes are created as subclasses ofdjango.forms.Form,including theModelForm, which you encounterin Django’s admin.
Models and Forms
In fact if your form is going to be used to directly add or edit a Djangomodel, aModelForm can save you a greatdeal of time, effort, and code, because it will build a form, along with theappropriate fields and their attributes, from aModel class.
Bound and unbound form instances¶
The distinction betweenBound and unbound forms is important:
- An unbound form has no data associated with it. When rendered to the user,it will be empty or will contain default values.
- A bound form has submitted data, and hence can be used to tell if that datais valid. If an invalid bound form is rendered, it can include inline errormessages telling the user what data to correct.
The form’sis_bound attribute will tell you whether a form hasdata bound to it or not.
More on fields¶
Consider a more useful form than our minimal example above, which we could useto implement “contact me” functionality on a personal website:
fromdjangoimportformsclassContactForm(forms.Form):subject=forms.CharField(max_length=100)message=forms.CharField(widget=forms.Textarea)sender=forms.EmailField()cc_myself=forms.BooleanField(required=False)
Our earlier form used a single field,your_name, aCharField. Inthis case, our form has four fields:subject,message,sender andcc_myself.CharField,EmailField andBooleanField are just three of the available field types; a full listcan be found inForm fields.
Widgets¶
Each form field has a correspondingWidget class,which in turn corresponds to an HTML form widget such as<inputtype="text">.
In most cases, the field will have a sensible default widget. For example, bydefault, aCharField will have aTextInput widget, thatproduces an<inputtype="text"> in the HTML. If you needed<textarea>instead, you’d specify the appropriate widget when defining your form field,as we have done for themessage field.
Field data¶
Whatever the data submitted with a form, once it has been successfullyvalidated by callingis_valid() (andis_valid() has returnedTrue),the validated form data will be in theform.cleaned_data dictionary. Thisdata will have been nicely converted into Python types for you.
Note
You can still access the unvalidated data directly fromrequest.POST atthis point, but the validated data is better.
In the contact form example above,cc_myself will be a boolean value.Likewise, fields such asIntegerField andFloatField convertvalues to a Pythonint andfloat respectively.
Here’s how the form data could be processed in the view that handles this form:
fromdjango.core.mailimportsend_mailifform.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']ifcc_myself:recipients.append(sender)send_mail(subject,message,sender,recipients)returnHttpResponseRedirect('/thanks/')
Tip
For more on sending email from Django, seeSending email.
Some field types need some extra handling. For example, files that are uploadedusing a form need to be handled differently (they can be retrieved fromrequest.FILES, rather thanrequest.POST). For details of how to handlefile uploads with your form, seeBinding uploaded files to a form.
Working with form templates¶
All you need to do to get your form into a template is to place the forminstance into the template context. So if your form is calledform in thecontext,{{form}} will render its<label> and<input> elementsappropriately.
Form rendering options¶
Additional form template furniture
Don’t forget that a form’s output doesnot include the surrounding<form> tags, or the form’ssubmit control. You will have to providethese yourself.
There are other output options though for the<label>/<input> pairs:
{{form.as_table}}will render them as table cells wrapped in<tr>tags{{form.as_p}}will render them wrapped in<p>tags{{form.as_ul}}will render them wrapped in<li>tags
Note that you’ll have to provide the surrounding<table> or<ul>elements yourself.
Here’s the output of{{form.as_p}} for ourContactForm instance:
<p><labelfor="id_subject">Subject:</label><inputid="id_subject"type="text"name="subject"maxlength="100"required/></p><p><labelfor="id_message">Message:</label><textareaname="message"id="id_message"required></textarea></p><p><labelfor="id_sender">Sender:</label><inputtype="email"name="sender"id="id_sender"required/></p><p><labelfor="id_cc_myself">Cc myself:</label><inputtype="checkbox"name="cc_myself"id="id_cc_myself"/></p>
Note that each form field has an ID attribute set toid_<field-name>, whichis referenced by the accompanying label tag. This is important in ensuring thatforms are accessible to assistive technology such as screen reader software.You can alsocustomize the way in which labels and ids are generated.
SeeOutputting forms as HTML for more on this.
Rendering fields manually¶
We don’t have to let Django unpack the form’s fields; we can do it manually ifwe like (allowing us to reorder the fields, for example). Each field isavailable as an attribute of the form using{{form.name_of_field}}, andin a Django template, will be rendered appropriately. For example:
{{form.non_field_errors}}<divclass="fieldWrapper">{{form.subject.errors}}<labelfor="{{form.subject.id_for_label}}">Email subject:</label>{{form.subject}}</div><divclass="fieldWrapper">{{form.message.errors}}<labelfor="{{form.message.id_for_label}}">Your message:</label>{{form.message}}</div><divclass="fieldWrapper">{{form.sender.errors}}<labelfor="{{form.sender.id_for_label}}">Your email address:</label>{{form.sender}}</div><divclass="fieldWrapper">{{form.cc_myself.errors}}<labelfor="{{form.cc_myself.id_for_label}}">CC yourself?</label>{{form.cc_myself}}</div>
Complete<label> elements can also be generated using thelabel_tag(). For example:
<divclass="fieldWrapper">{{form.subject.errors}}{{form.subject.label_tag}}{{form.subject}}</div>
Rendering form error messages¶
Of course, the price of this flexibility is more work. Until now we haven’t hadto worry about how to display form errors, because that’s taken care of for us.In this example we have had to make sure we take care of any errors for eachfield and any errors for the form as a whole. Note{{form.non_field_errors}} at the top of the form and the template lookup for errors on each field.
Using{{form.name_of_field.errors}} displays a list of form errors,rendered as an unordered list. This might look like:
<ulclass="errorlist"><li>Sender is required.</li></ul>
The list has a CSS class oferrorlist to allow you to style its appearance.If you wish to further customize the display of errors you can do so by loopingover them:
{%ifform.subject.errors%}<ol>{%forerrorinform.subject.errors%}<li><strong>{{error|escape}}</strong></li>{%endfor%}</ol>{%endif%}
Non-field errors (and/or hidden field errors that are rendered at the top ofthe form when using helpers likeform.as_p()) will be rendered with anadditional class ofnonfield to help distinguish them from field-specificerrors. For example,{{form.non_field_errors}} would look like:
<ulclass="errorlist nonfield"><li>Generic validation error</li></ul>
SeeThe Forms API for more on errors, styling, and working with formattributes in templates.
Looping over the form’s fields¶
If you’re using the same HTML for each of your form fields, you can reduceduplicate code by looping through each field in turn using a{%for%}loop:
{%forfieldinform%}<divclass="fieldWrapper">{{field.errors}}{{field.label_tag}}{{field}}{%iffield.help_text%}<pclass="help">{{field.help_text|safe}}</p>{%endif%}</div>{%endfor%}
Useful attributes on{{field}} include:
{{field.label}}- The label of the field, e.g.
Emailaddress. {{field.label_tag}}The field’s label wrapped in the appropriate HTML
<label>tag. Thisincludes the form’slabel_suffix. For example,the defaultlabel_suffixis a colon:<labelfor="id_email">Emailaddress:</label>
{{field.id_for_label}}- The ID that will be used for this field (
id_emailin the exampleabove). If you are constructing the label manually, you may want to usethis in lieu oflabel_tag. It’s also useful, for example, if you havesome inline JavaScript and want to avoid hardcoding the field’s ID. {{field.value}}- The value of the field. e.g
someone@example.com. {{field.html_name}}- The name of the field that will be used in the input element’s namefield. This takes the form prefix into account, if it has been set.
{{field.help_text}}- Any help text that has been associated with the field.
{{field.errors}}- Outputs a
<ulclass="errorlist">containing any validation errorscorresponding to this field. You can customize the presentation ofthe errors with a{%forerrorinfield.errors%}loop. In thiscase, each object in the loop is a simple string containing the errormessage. {{field.is_hidden}}- This attribute is
Trueif the form field is a hidden field andFalseotherwise. It’s not particularly useful as a templatevariable, but could be useful in conditional tests such as:
{%iffield.is_hidden%}{# Do something special #}{%endif%}
{{field.field}}- The
Fieldinstance from the form class thatthisBoundFieldwraps. You can use it to accessFieldattributes, e.g.{{char_field.field.max_length}}.
See also
For a complete list of attributes and methods, seeBoundField.
Looping over hidden and visible fields¶
If you’re manually laying out a form in a template, as opposed to relying onDjango’s default form layout, you might want to treat<inputtype="hidden">fields differently from non-hidden fields. For example, because hidden fieldsdon’t display anything, putting error messages “next to” the field could causeconfusion for your users – so errors for those fields should be handleddifferently.
Django provides two methods on a form that allow you to loop over the hiddenand visible fields independently:hidden_fields() andvisible_fields(). Here’s a modification of an earlier example that usesthese two methods:
{# Include the hidden fields #}{%forhiddeninform.hidden_fields%}{{hidden}}{%endfor%}{# Include the visible fields #}{%forfieldinform.visible_fields%}<divclass="fieldWrapper">{{field.errors}}{{field.label_tag}}{{field}}</div>{%endfor%}
This example does not handle any errors in the hidden fields. Usually, anerror in a hidden field is a sign of form tampering, since normal forminteraction won’t alter them. However, you could easily insert some errordisplays for those form errors, as well.
Reusable form templates¶
If your site uses the same rendering logic for forms in multiple places, youcan reduce duplication by saving the form’s loop in a standalone template andusing theinclude tag to reuse it in other templates:
# In your form template:{%include"form_snippet.html"%}# In form_snippet.html:{%forfieldinform%}<divclass="fieldWrapper">{{field.errors}}{{field.label_tag}}{{field}}</div>{%endfor%}
If the form object passed to a template has a different name within thecontext, you can alias it using thewith argument of theincludetag:
{%include"form_snippet.html"withform=comment_form%}
If you find yourself doing this often, you might consider creating a custominclusion tag.
Further topics¶
This covers the basics, but forms can do a whole lot more:
See also
- The Forms Reference
- Covers the full API reference, including form fields, form widgets,and form and field validation.

