summaryrefslogtreecommitdiff
path: root/docs/topics/forms/index.txt
blob: c5d33f0e54687e0c12938b32c76319058db52d06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
==================
Working with forms
==================

.. admonition:: About this document

    This document provides an introduction to Django's form handling features.
    For a more detailed look at specific areas of the forms API, see
    :doc:`/ref/forms/api`, :doc:`/ref/forms/fields`, and
    :doc:`/ref/forms/validation`.

.. highlightlang:: html+django

``django.forms`` is Django's form-handling library.

While it is possible to process form submissions just using Django's
:class:`~django.http.HttpRequest` class, using the form library takes care of a
number of common form-related tasks. Using it, you can:

1. Display an HTML form with automatically generated form widgets.
2. Check submitted data against a set of validation rules.
3. Redisplay a form in the case of validation errors.
4. Convert submitted form data to the relevant Python data types.

Overview
========

The library deals with these concepts:

.. glossary::

    Widget
        A class that corresponds to an HTML form widget, e.g.
        ``<input type="text">`` or ``<textarea>``. This handles rendering of the
        widget as HTML.

    Field
        A class that is responsible for doing validation, e.g.
        an ``EmailField`` that makes sure its data is a valid email address.

    Form
        A collection of fields that knows how to validate itself and
        display itself as HTML.

    Form Media
        The CSS and JavaScript resources that are required to render a form.

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

Form objects
============

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.

For example, consider a form used to implement "contact me" functionality on a
personal Web site:

.. code-block:: python

    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`` and ``cc_myself``. ``CharField``,
``EmailField`` and ``BooleanField`` are just three of the available field types;
a full list can be found in :doc:`/ref/forms/fields`.

If your form is going to be used to directly add or edit a Django model, you can
use a :doc:`ModelForm </topics/forms/modelforms>` to avoid duplicating your model
description.

Using a form in a view
----------------------

The standard pattern for processing a form in a view looks like this:

.. code-block:: python

   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_to_response('contact.html', {
           'form': form,
       })


There are three code paths here:

1. If the form has not been submitted, an unbound instance of ContactForm is
   created and passed to the template.
2. If the form has been submitted, a bound instance of the form is created
   using ``request.POST``. If the submitted data is valid, it is processed
   and the user is re-directed to a "thanks" page.
3. If the form has been submitted but is invalid, the bound form instance is
   passed on to the template.

The distinction between **bound** and **unbound** forms is important. An unbound
form does not have any data associated with it; when rendered to the user, it
will be empty or will contain default values. A bound form does have submitted
data, and hence can be used to tell if that data is valid. If an invalid bound
form is rendered it can include inline error messages telling the user where
they went wrong.

See :ref:`ref-forms-api-bound-unbound` for further information on the
differences between bound and unbound forms.

Handling file uploads with a form
---------------------------------

To see how to handle file uploads with your form see
:ref:`binding-uploaded-files` for more information.

Processing the data from a form
-------------------------------

Once ``is_valid()`` returns ``True``, you can process the form submission safe
in the knowledge that it conforms to the validation rules defined by your form.
While you could access ``request.POST`` directly at this point, it is better to
access ``form.cleaned_data``. This data has not only been validated but will
also be converted in to the relevant Python types for you. In the above example,
``cc_myself`` will be a boolean value. Likewise, fields such as ``IntegerField``
and ``FloatField`` convert values to a Python int and float respectively. Note
that read-only fields are not available in ``form.cleaned_data`` (and setting
a value in a custom ``clean()`` method won't have any effect) because these
fields are displayed as text rather than as input elements, and thus are not
posted back to the server.

Extending the above example, here's how the form data could be processed:

.. code-block:: python

    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

For more on sending email from Django, see :doc:`/topics/email`.

Displaying a form using a template
----------------------------------

Forms are designed to work with the Django template language. In the above
example, we passed our ``ContactForm`` 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.

.. admonition:: Forms and Cross Site Request Forgery protection

   Django ships with an easy-to-use :doc:`protection against Cross Site Request
   Forgeries </ref/contrib/csrf>`. When submitting a form via POST with
   CSRF protection enabled you must use the :ttag:`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 :ref:`customize the way in which labels and ids are generated
<ref-forms-api-configuring-label>`.

You can also use ``form.as_table`` to output table rows (you'll need to provide
your own ``<table>`` tags) and ``form.as_ul`` to output list items.

Customizing the form template
-----------------------------

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>

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

Looping over the form's fields
------------------------------

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>

Within this loop, ``{{ field }}`` is an instance of :class:`BoundField`.
``BoundField`` also has the following attributes, which can be useful in your
templates:

``{{ field.label }}``
    The label of the field, e.g. ``Email address``.

``{{ field.label_tag }}``
    The field's label wrapped in the appropriate HTML ``<label>`` tag,
    e.g. ``<label for="id_email">Email address</label>``

``{{ field.html_name }}``
    The name of the field that will be used in the input element's name
    field. 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 ``<ul class="errorlist">`` containing any validation errors
    corresponding to this field. You can customize the presentation of
    the errors with a ``{% for error in field.errors %}`` loop. In this
    case, each object in the loop is a simple string containing the error
    message.

``field.is_hidden``
    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 %}

Looping over hidden and visible fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you're manually laying out a form in a template, as opposed to relying on
Django's default form layout, you might want to treat ``<input type="hidden">``
fields differently than non-hidden fields. For example, because hidden fields
don't display anything, putting error messages "next to" the field could cause
confusion for your users -- so errors for those fields should be handled
differently.

Django provides two methods on a form that allow you to loop over the hidden
and visible fields independently: ``hidden_fields()`` and
``visible_fields()``. Here's a modification of an earlier example that uses
these two methods::

    <form action="/contact/" method="post">
        {# Include the hidden fields #}
        {% for hidden in form.hidden_fields %}
        {{ hidden }}
        {% endfor %}
        {# Include the visible fields #}
        {% for field in form.visible_fields %}
            <div class="fieldWrapper">
                {{ field.errors }}
                {{ field.label_tag }}: {{ field }}
            </div>
        {% endfor %}
        <p><input type="submit" value="Send message" /></p>
    </form>

This example does not handle any errors in the hidden fields. Usually, an
error in a hidden field is a sign of form tampering, since normal form
interaction won't alter them. However, you could easily insert some error
displays for those form errors, as well.

Reusable form templates
-----------------------

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 :ttag:`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 %}

If the form object passed to a template has a different name within the
context, you can alias it using the ``with`` argument of the :ttag:`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>

If you find yourself doing this often, you might consider creating a custom
:ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`.

Further topics
==============

This covers the basics, but forms can do a whole lot more:

.. toctree::
   :maxdepth: 2

   formsets
   modelforms
   media

.. seealso::

    :doc:`The Forms Reference </ref/forms/index>`
        Covers the full API reference, including form fields, form widgets,
        and form and field validation.