mirror of
https://github.com/django/django.git
synced 2024-11-29 14:46:18 +01:00
456466d932
Thanks Carlton Gibson, Keryn Knight, Mariusz Felisiak, and Nick Pope for reviews. Co-authored-by: Johannes Hoppe <info@johanneshoppe.com>
1438 lines
60 KiB
Plaintext
1438 lines
60 KiB
Plaintext
=============
|
|
The Forms API
|
|
=============
|
|
|
|
.. module:: django.forms
|
|
|
|
.. admonition:: About this document
|
|
|
|
This document covers the gritty details of Django's forms API. You should
|
|
read the :doc:`introduction to working with forms </topics/forms/index>`
|
|
first.
|
|
|
|
.. _ref-forms-api-bound-unbound:
|
|
|
|
Bound and unbound forms
|
|
=======================
|
|
|
|
A :class:`Form` instance is either **bound** to a set of data, or **unbound**.
|
|
|
|
* If it's **bound** to a set of data, it's capable of validating that data
|
|
and rendering the form as HTML with the data displayed in the HTML.
|
|
|
|
* If it's **unbound**, it cannot do validation (because there's no data to
|
|
validate!), but it can still render the blank form as HTML.
|
|
|
|
.. class:: Form
|
|
|
|
To create an unbound :class:`Form` instance, instantiate the class::
|
|
|
|
>>> f = ContactForm()
|
|
|
|
To bind data to a form, pass the data as a dictionary as the first parameter to
|
|
your :class:`Form` class constructor::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
|
|
In this dictionary, the keys are the field names, which correspond to the
|
|
attributes in your :class:`Form` class. The values are the data you're trying to
|
|
validate. These will usually be strings, but there's no requirement that they be
|
|
strings; the type of data you pass depends on the :class:`Field`, as we'll see
|
|
in a moment.
|
|
|
|
.. attribute:: Form.is_bound
|
|
|
|
If you need to distinguish between bound and unbound form instances at runtime,
|
|
check the value of the form's :attr:`~Form.is_bound` attribute::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.is_bound
|
|
False
|
|
>>> f = ContactForm({'subject': 'hello'})
|
|
>>> f.is_bound
|
|
True
|
|
|
|
Note that passing an empty dictionary creates a *bound* form with empty data::
|
|
|
|
>>> f = ContactForm({})
|
|
>>> f.is_bound
|
|
True
|
|
|
|
If you have a bound :class:`Form` instance and want to change the data somehow,
|
|
or if you want to bind an unbound :class:`Form` instance to some data, create
|
|
another :class:`Form` instance. There is no way to change data in a
|
|
:class:`Form` instance. Once a :class:`Form` instance has been created, you
|
|
should consider its data immutable, whether it has data or not.
|
|
|
|
Using forms to validate data
|
|
============================
|
|
|
|
.. method:: Form.clean()
|
|
|
|
Implement a ``clean()`` method on your ``Form`` when you must add custom
|
|
validation for fields that are interdependent. See
|
|
:ref:`validating-fields-with-clean` for example usage.
|
|
|
|
.. method:: Form.is_valid()
|
|
|
|
The primary task of a :class:`Form` object is to validate data. With a bound
|
|
:class:`Form` instance, call the :meth:`~Form.is_valid` method to run validation
|
|
and return a boolean designating whether the data was valid::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
|
|
Let's try with some invalid data. In this case, ``subject`` is blank (an error,
|
|
because all fields are required by default) and ``sender`` is not a valid
|
|
email address::
|
|
|
|
>>> data = {'subject': '',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'invalid email address',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
False
|
|
|
|
.. attribute:: Form.errors
|
|
|
|
Access the :attr:`~Form.errors` attribute to get a dictionary of error
|
|
messages::
|
|
|
|
>>> f.errors
|
|
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}
|
|
|
|
In this dictionary, the keys are the field names, and the values are lists of
|
|
strings representing the error messages. The error messages are stored
|
|
in lists because a field can have multiple error messages.
|
|
|
|
You can access :attr:`~Form.errors` without having to call
|
|
:meth:`~Form.is_valid` first. The form's data will be validated the first time
|
|
either you call :meth:`~Form.is_valid` or access :attr:`~Form.errors`.
|
|
|
|
The validation routines will only get called once, regardless of how many times
|
|
you access :attr:`~Form.errors` or call :meth:`~Form.is_valid`. This means that
|
|
if validation has side effects, those side effects will only be triggered once.
|
|
|
|
.. method:: Form.errors.as_data()
|
|
|
|
Returns a ``dict`` that maps fields to their original ``ValidationError``
|
|
instances.
|
|
|
|
>>> f.errors.as_data()
|
|
{'sender': [ValidationError(['Enter a valid email address.'])],
|
|
'subject': [ValidationError(['This field is required.'])]}
|
|
|
|
Use this method anytime you need to identify an error by its ``code``. This
|
|
enables things like rewriting the error's message or writing custom logic in a
|
|
view when a given error is present. It can also be used to serialize the errors
|
|
in a custom format (e.g. XML); for instance, :meth:`~Form.errors.as_json()`
|
|
relies on ``as_data()``.
|
|
|
|
The need for the ``as_data()`` method is due to backwards compatibility.
|
|
Previously ``ValidationError`` instances were lost as soon as their
|
|
**rendered** error messages were added to the ``Form.errors`` dictionary.
|
|
Ideally ``Form.errors`` would have stored ``ValidationError`` instances
|
|
and methods with an ``as_`` prefix could render them, but it had to be done
|
|
the other way around in order not to break code that expects rendered error
|
|
messages in ``Form.errors``.
|
|
|
|
.. method:: Form.errors.as_json(escape_html=False)
|
|
|
|
Returns the errors serialized as JSON.
|
|
|
|
>>> f.errors.as_json()
|
|
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
|
|
"subject": [{"message": "This field is required.", "code": "required"}]}
|
|
|
|
By default, ``as_json()`` does not escape its output. If you are using it for
|
|
something like AJAX requests to a form view where the client interprets the
|
|
response and inserts errors into the page, you'll want to be sure to escape the
|
|
results on the client-side to avoid the possibility of a cross-site scripting
|
|
attack. You can do this in JavaScript with ``element.textContent = errorText``
|
|
or with jQuery's ``$(el).text(errorText)`` (rather than its ``.html()``
|
|
function).
|
|
|
|
If for some reason you don't want to use client-side escaping, you can also
|
|
set ``escape_html=True`` and error messages will be escaped so you can use them
|
|
directly in HTML.
|
|
|
|
.. method:: Form.errors.get_json_data(escape_html=False)
|
|
|
|
Returns the errors as a dictionary suitable for serializing to JSON.
|
|
:meth:`Form.errors.as_json()` returns serialized JSON, while this returns the
|
|
error data before it's serialized.
|
|
|
|
The ``escape_html`` parameter behaves as described in
|
|
:meth:`Form.errors.as_json()`.
|
|
|
|
.. method:: Form.add_error(field, error)
|
|
|
|
This method allows adding errors to specific fields from within the
|
|
``Form.clean()`` method, or from outside the form altogether; for instance
|
|
from a view.
|
|
|
|
The ``field`` argument is the name of the field to which the errors
|
|
should be added. If its value is ``None`` the error will be treated as
|
|
a non-field error as returned by :meth:`Form.non_field_errors()
|
|
<django.forms.Form.non_field_errors>`.
|
|
|
|
The ``error`` argument can be a string, or preferably an instance of
|
|
``ValidationError``. See :ref:`raising-validation-error` for best practices
|
|
when defining form errors.
|
|
|
|
Note that ``Form.add_error()`` automatically removes the relevant field from
|
|
``cleaned_data``.
|
|
|
|
.. method:: Form.has_error(field, code=None)
|
|
|
|
This method returns a boolean designating whether a field has an error with
|
|
a specific error ``code``. If ``code`` is ``None``, it will return ``True``
|
|
if the field contains any errors at all.
|
|
|
|
To check for non-field errors use
|
|
:data:`~django.core.exceptions.NON_FIELD_ERRORS` as the ``field`` parameter.
|
|
|
|
.. method:: Form.non_field_errors()
|
|
|
|
This method returns the list of errors from :attr:`Form.errors
|
|
<django.forms.Form.errors>` that aren't associated with a particular field.
|
|
This includes ``ValidationError``\s that are raised in :meth:`Form.clean()
|
|
<django.forms.Form.clean>` and errors added using :meth:`Form.add_error(None,
|
|
"...") <django.forms.Form.add_error>`.
|
|
|
|
Behavior of unbound forms
|
|
-------------------------
|
|
|
|
It's meaningless to validate a form with no data, but, for the record, here's
|
|
what happens with unbound forms::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.is_valid()
|
|
False
|
|
>>> f.errors
|
|
{}
|
|
|
|
.. _ref-forms-initial-form-values:
|
|
|
|
Initial form values
|
|
===================
|
|
|
|
.. attribute:: Form.initial
|
|
|
|
Use :attr:`~Form.initial` to declare the initial value of form fields at
|
|
runtime. For example, you might want to fill in a ``username`` field with the
|
|
username of the current session.
|
|
|
|
To accomplish this, use the :attr:`~Form.initial` argument to a :class:`Form`.
|
|
This argument, if given, should be a dictionary mapping field names to initial
|
|
values. Only include the fields for which you're specifying an initial value;
|
|
it's not necessary to include every field in your form. For example::
|
|
|
|
>>> f = ContactForm(initial={'subject': 'Hi there!'})
|
|
|
|
These values are only displayed for unbound forms, and they're not used as
|
|
fallback values if a particular value isn't provided.
|
|
|
|
If a :class:`~django.forms.Field` defines :attr:`~Field.initial` *and* you
|
|
include :attr:`~Form.initial` when instantiating the ``Form``, then the latter
|
|
``initial`` will have precedence. In this example, ``initial`` is provided both
|
|
at the field level and at the form instance level, and the latter gets
|
|
precedence::
|
|
|
|
>>> from django import forms
|
|
>>> class CommentForm(forms.Form):
|
|
... name = forms.CharField(initial='class')
|
|
... url = forms.URLField()
|
|
... comment = forms.CharField()
|
|
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
|
|
>>> print(f)
|
|
<tr><th>Name:</th><td><input type="text" name="name" value="instance" required></td></tr>
|
|
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
|
|
<tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr>
|
|
|
|
.. method:: Form.get_initial_for_field(field, field_name)
|
|
|
|
Returns the initial data for a form field. It retrieves the data from
|
|
:attr:`Form.initial` if present, otherwise trying :attr:`Field.initial`.
|
|
Callable values are evaluated.
|
|
|
|
It is recommended to use :attr:`BoundField.initial` over
|
|
:meth:`~Form.get_initial_for_field()` because ``BoundField.initial`` has a
|
|
simpler interface. Also, unlike :meth:`~Form.get_initial_for_field()`,
|
|
:attr:`BoundField.initial` caches its values. This is useful especially when
|
|
dealing with callables whose return values can change (e.g. ``datetime.now`` or
|
|
``uuid.uuid4``)::
|
|
|
|
>>> import uuid
|
|
>>> class UUIDCommentForm(CommentForm):
|
|
... identifier = forms.UUIDField(initial=uuid.uuid4)
|
|
>>> f = UUIDCommentForm()
|
|
>>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
|
|
UUID('972ca9e4-7bfe-4f5b-af7d-07b3aa306334')
|
|
>>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
|
|
UUID('1b411fab-844e-4dec-bd4f-e9b0495f04d0')
|
|
>>> # Using BoundField.initial, for comparison
|
|
>>> f['identifier'].initial
|
|
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
|
|
>>> f['identifier'].initial
|
|
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
|
|
|
|
Checking which form data has changed
|
|
====================================
|
|
|
|
.. method:: Form.has_changed()
|
|
|
|
Use the ``has_changed()`` method on your ``Form`` when you need to check if the
|
|
form data has been changed from the initial data.
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data, initial=data)
|
|
>>> f.has_changed()
|
|
False
|
|
|
|
When the form is submitted, we reconstruct it and provide the original data
|
|
so that the comparison can be done:
|
|
|
|
>>> f = ContactForm(request.POST, initial=data)
|
|
>>> f.has_changed()
|
|
|
|
``has_changed()`` will be ``True`` if the data from ``request.POST`` differs
|
|
from what was provided in :attr:`~Form.initial` or ``False`` otherwise. The
|
|
result is computed by calling :meth:`Field.has_changed` for each field in the
|
|
form.
|
|
|
|
.. attribute:: Form.changed_data
|
|
|
|
The ``changed_data`` attribute returns a list of the names of the fields whose
|
|
values in the form's bound data (usually ``request.POST``) differ from what was
|
|
provided in :attr:`~Form.initial`. It returns an empty list if no data differs.
|
|
|
|
>>> f = ContactForm(request.POST, initial=data)
|
|
>>> if f.has_changed():
|
|
... print("The following fields changed: %s" % ", ".join(f.changed_data))
|
|
>>> f.changed_data
|
|
['subject', 'message']
|
|
|
|
Accessing the fields from the form
|
|
==================================
|
|
|
|
.. attribute:: Form.fields
|
|
|
|
You can access the fields of :class:`Form` instance from its ``fields``
|
|
attribute::
|
|
|
|
>>> for row in f.fields.values(): print(row)
|
|
...
|
|
<django.forms.fields.CharField object at 0x7ffaac632510>
|
|
<django.forms.fields.URLField object at 0x7ffaac632f90>
|
|
<django.forms.fields.CharField object at 0x7ffaac3aa050>
|
|
>>> f.fields['name']
|
|
<django.forms.fields.CharField object at 0x7ffaac6324d0>
|
|
|
|
You can alter the field of :class:`Form` instance to change the way it is
|
|
presented in the form::
|
|
|
|
>>> f.as_table().split('\n')[0]
|
|
'<tr><th>Name:</th><td><input name="name" type="text" value="instance" required></td></tr>'
|
|
>>> f.fields['name'].label = "Username"
|
|
>>> f.as_table().split('\n')[0]
|
|
'<tr><th>Username:</th><td><input name="name" type="text" value="instance" required></td></tr>'
|
|
|
|
Beware not to alter the ``base_fields`` attribute because this modification
|
|
will influence all subsequent ``ContactForm`` instances within the same Python
|
|
process::
|
|
|
|
>>> f.base_fields['name'].label = "Username"
|
|
>>> another_f = CommentForm(auto_id=False)
|
|
>>> another_f.as_table().split('\n')[0]
|
|
'<tr><th>Username:</th><td><input name="name" type="text" value="class" required></td></tr>'
|
|
|
|
Accessing "clean" data
|
|
======================
|
|
|
|
.. attribute:: Form.cleaned_data
|
|
|
|
Each field in a :class:`Form` class is responsible not only for validating
|
|
data, but also for "cleaning" it -- normalizing it to a consistent format. This
|
|
is a nice feature, because it allows data for a particular field to be input in
|
|
a variety of ways, always resulting in consistent output.
|
|
|
|
For example, :class:`~django.forms.DateField` normalizes input into a
|
|
Python ``datetime.date`` object. Regardless of whether you pass it a string in
|
|
the format ``'1994-07-15'``, a ``datetime.date`` object, or a number of other
|
|
formats, ``DateField`` will always normalize it to a ``datetime.date`` object
|
|
as long as it's valid.
|
|
|
|
Once you've created a :class:`~Form` instance with a set of data and validated
|
|
it, you can access the clean data via its ``cleaned_data`` attribute::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
>>> f.cleaned_data
|
|
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
|
|
|
|
Note that any text-based field -- such as ``CharField`` or ``EmailField`` --
|
|
always cleans the input into a string. We'll cover the encoding implications
|
|
later in this document.
|
|
|
|
If your data does *not* validate, the ``cleaned_data`` dictionary contains
|
|
only the valid fields::
|
|
|
|
>>> data = {'subject': '',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'invalid email address',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
False
|
|
>>> f.cleaned_data
|
|
{'cc_myself': True, 'message': 'Hi there'}
|
|
|
|
``cleaned_data`` will always *only* contain a key for fields defined in the
|
|
``Form``, even if you pass extra data when you define the ``Form``. In this
|
|
example, we pass a bunch of extra fields to the ``ContactForm`` constructor,
|
|
but ``cleaned_data`` contains only the form's fields::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True,
|
|
... 'extra_field_1': 'foo',
|
|
... 'extra_field_2': 'bar',
|
|
... 'extra_field_3': 'baz'}
|
|
>>> f = ContactForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
>>> f.cleaned_data # Doesn't contain extra_field_1, etc.
|
|
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
|
|
|
|
When the ``Form`` is valid, ``cleaned_data`` will include a key and value for
|
|
*all* its fields, even if the data didn't include a value for some optional
|
|
fields. In this example, the data dictionary doesn't include a value for the
|
|
``nick_name`` field, but ``cleaned_data`` includes it, with an empty value::
|
|
|
|
>>> from django import forms
|
|
>>> class OptionalPersonForm(forms.Form):
|
|
... first_name = forms.CharField()
|
|
... last_name = forms.CharField()
|
|
... nick_name = forms.CharField(required=False)
|
|
>>> data = {'first_name': 'John', 'last_name': 'Lennon'}
|
|
>>> f = OptionalPersonForm(data)
|
|
>>> f.is_valid()
|
|
True
|
|
>>> f.cleaned_data
|
|
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}
|
|
|
|
In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an
|
|
empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat
|
|
empty values as an empty string. Each field type knows what its "blank" value
|
|
is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For
|
|
full details on each field's behavior in this case, see the "Empty value" note
|
|
for each field in the "Built-in ``Field`` classes" section below.
|
|
|
|
You can write code to perform validation for particular form fields (based on
|
|
their name) or for the form as a whole (considering combinations of various
|
|
fields). More information about this is in :doc:`/ref/forms/validation`.
|
|
|
|
.. _ref-forms-api-outputting-html:
|
|
|
|
Outputting forms as HTML
|
|
========================
|
|
|
|
The second task of a ``Form`` object is to render itself as HTML. To do so,
|
|
``print`` it::
|
|
|
|
>>> f = ContactForm()
|
|
>>> print(f)
|
|
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>
|
|
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>
|
|
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>
|
|
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>
|
|
|
|
If the form is bound to data, the HTML output will include that data
|
|
appropriately. For example, if a field is represented by an
|
|
``<input type="text">``, the data will be in the ``value`` attribute. If a
|
|
field is represented by an ``<input type="checkbox">``, then that HTML will
|
|
include ``checked`` if appropriate::
|
|
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data)
|
|
>>> print(f)
|
|
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" required></td></tr>
|
|
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" required></td></tr>
|
|
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="foo@example.com" required></td></tr>
|
|
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked></td></tr>
|
|
|
|
This default output is a two-column HTML table, with a ``<tr>`` for each field.
|
|
Notice the following:
|
|
|
|
* For flexibility, the output does *not* include the ``<table>`` and
|
|
``</table>`` tags, nor does it include the ``<form>`` and ``</form>``
|
|
tags or an ``<input type="submit">`` tag. It's your job to do that.
|
|
|
|
* Each field type has a default HTML representation. ``CharField`` is
|
|
represented by an ``<input type="text">`` and ``EmailField`` by an
|
|
``<input type="email">``. ``BooleanField(null=False)`` is represented by an
|
|
``<input type="checkbox">``. Note these are merely sensible defaults; you can
|
|
specify which HTML to use for a given field by using widgets, which we'll
|
|
explain shortly.
|
|
|
|
* The HTML ``name`` for each tag is taken directly from its attribute name
|
|
in the ``ContactForm`` class.
|
|
|
|
* The text label for each field -- e.g. ``'Subject:'``, ``'Message:'`` and
|
|
``'Cc myself:'`` is generated from the field name by converting all
|
|
underscores to spaces and upper-casing the first letter. Again, note
|
|
these are merely sensible defaults; you can also specify labels manually.
|
|
|
|
* Each text label is surrounded in an HTML ``<label>`` tag, which points
|
|
to the appropriate form field via its ``id``. Its ``id``, in turn, is
|
|
generated by prepending ``'id_'`` to the field name. The ``id``
|
|
attributes and ``<label>`` tags are included in the output by default, to
|
|
follow best practices, but you can change that behavior.
|
|
|
|
* The output uses HTML5 syntax, targeting ``<!DOCTYPE html>``. For example,
|
|
it uses boolean attributes such as ``checked`` rather than the XHTML style
|
|
of ``checked='checked'``.
|
|
|
|
Although ``<table>`` output is the default output style when you ``print`` a
|
|
form, other output styles are available. Each style is available as a method on
|
|
a form object, and each rendering method returns a string.
|
|
|
|
``template_name``
|
|
-----------------
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
.. attribute:: Form.template_name
|
|
|
|
The name of a template that is going to be rendered if the form is cast into a
|
|
string, e.g. via ``print(form)`` or in a template via ``{{ form }}``. By
|
|
default this template is ``'django/forms/default.html'``, which is a proxy for
|
|
``'django/forms/table.html'``. The template can be changed per form by
|
|
overriding the ``template_name`` attribute or more generally by overriding the
|
|
default template, see also :ref:`overriding-built-in-form-templates`.
|
|
|
|
``template_name_label``
|
|
-----------------------
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
.. attribute:: Form.template_name_label
|
|
|
|
The template used to render a field's ``<label>``, used when calling
|
|
:meth:`BoundField.label_tag`. Can be changed per form by overriding this
|
|
attribute or more generally by overriding the default template, see also
|
|
:ref:`overriding-built-in-form-templates`.
|
|
|
|
``as_p()``
|
|
----------
|
|
|
|
.. method:: Form.as_p()
|
|
|
|
``as_p()`` renders the form using the template assigned to the forms
|
|
``template_name_p`` attribute, by default this template is
|
|
``'django/forms/p.html'``. This template renders the form as a series of
|
|
``<p>`` tags, with each ``<p>`` containing one field::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.as_p()
|
|
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" required></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>'
|
|
>>> print(f.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> <input type="text" name="message" id="id_message" required></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>
|
|
|
|
``as_ul()``
|
|
-----------
|
|
|
|
.. method:: Form.as_ul()
|
|
|
|
``as_ul()`` renders the form using the template assigned to the forms
|
|
``template_name_ul`` attribute, by default this template is
|
|
``'django/forms/ul.html'``. This template renders the form as a series of
|
|
``<li>`` tags, with each ``<li>`` containing one field. It does *not* include
|
|
the ``<ul>`` or ``</ul>``, so that you can specify any HTML attributes on the
|
|
``<ul>`` for flexibility::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.as_ul()
|
|
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>'
|
|
>>> print(f.as_ul())
|
|
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required></li>
|
|
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required></li>
|
|
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required></li>
|
|
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"></li>
|
|
|
|
``as_table()``
|
|
--------------
|
|
|
|
.. method:: Form.as_table()
|
|
|
|
Finally, ``as_table()`` renders the form using the template assigned to the
|
|
forms ``template_name_table`` attribute, by default this template is
|
|
``'django/forms/table.html'``. This template outputs the form as an HTML
|
|
``<table>``::
|
|
|
|
>>> f = ContactForm()
|
|
>>> f.as_table()
|
|
'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>'
|
|
>>> print(f)
|
|
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" required></td></tr>
|
|
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" required></td></tr>
|
|
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" required></td></tr>
|
|
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself"></td></tr>
|
|
|
|
``get_context()``
|
|
-----------------
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
.. method:: Form.get_context()
|
|
|
|
Return context for form rendering in a template.
|
|
|
|
The available context is:
|
|
|
|
* ``form``: The bound form.
|
|
* ``fields``: All bound fields, except the hidden fields.
|
|
* ``hidden_fields``: All hidden bound fields.
|
|
* ``errors``: All non field related or hidden field related form errors.
|
|
|
|
``render()``
|
|
------------
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
.. method:: Form.render(template_name=None, context=None, renderer=None)
|
|
|
|
The render method is called by ``__str__`` as well as the
|
|
:meth:`.Form.as_table`, :meth:`.Form.as_p`, and :meth:`.Form.as_ul` methods.
|
|
All arguments are optional and default to:
|
|
|
|
* ``template_name``: :attr:`.Form.template_name`
|
|
* ``context``: Value returned by :meth:`.Form.get_context`
|
|
* ``renderer``: Value returned by :attr:`.Form.default_renderer`
|
|
|
|
.. _ref-forms-api-styling-form-rows:
|
|
|
|
Styling required or erroneous form rows
|
|
---------------------------------------
|
|
|
|
.. attribute:: Form.error_css_class
|
|
.. attribute:: Form.required_css_class
|
|
|
|
It's pretty common to style form rows and fields that are required or have
|
|
errors. For example, you might want to present required form rows in bold and
|
|
highlight errors in red.
|
|
|
|
The :class:`Form` class has a couple of hooks you can use to add ``class``
|
|
attributes to required rows or to rows with errors: set the
|
|
:attr:`Form.error_css_class` and/or :attr:`Form.required_css_class`
|
|
attributes::
|
|
|
|
from django import forms
|
|
|
|
class ContactForm(forms.Form):
|
|
error_css_class = 'error'
|
|
required_css_class = 'required'
|
|
|
|
# ... and the rest of your fields here
|
|
|
|
Once you've done that, rows will be given ``"error"`` and/or ``"required"``
|
|
classes, as needed. The HTML will look something like::
|
|
|
|
>>> f = ContactForm(data)
|
|
>>> print(f.as_table())
|
|
<tr class="required"><th><label class="required" for="id_subject">Subject:</label> ...
|
|
<tr class="required"><th><label class="required" for="id_message">Message:</label> ...
|
|
<tr class="required error"><th><label class="required" for="id_sender">Sender:</label> ...
|
|
<tr><th><label for="id_cc_myself">Cc myself:<label> ...
|
|
>>> f['subject'].label_tag()
|
|
<label class="required" for="id_subject">Subject:</label>
|
|
>>> f['subject'].label_tag(attrs={'class': 'foo'})
|
|
<label for="id_subject" class="foo required">Subject:</label>
|
|
|
|
.. _ref-forms-api-configuring-label:
|
|
|
|
Configuring form elements' HTML ``id`` attributes and ``<label>`` tags
|
|
----------------------------------------------------------------------
|
|
|
|
.. attribute:: Form.auto_id
|
|
|
|
By default, the form rendering methods include:
|
|
|
|
* HTML ``id`` attributes on the form elements.
|
|
|
|
* The corresponding ``<label>`` tags around the labels. An HTML ``<label>`` tag
|
|
designates which label text is associated with which form element. This small
|
|
enhancement makes forms more usable and more accessible to assistive devices.
|
|
It's always a good idea to use ``<label>`` tags.
|
|
|
|
The ``id`` attribute values are generated by prepending ``id_`` to the form
|
|
field names. This behavior is configurable, though, if you want to change the
|
|
``id`` convention or remove HTML ``id`` attributes and ``<label>`` tags
|
|
entirely.
|
|
|
|
Use the ``auto_id`` argument to the ``Form`` constructor to control the ``id``
|
|
and label behavior. This argument must be ``True``, ``False`` or a string.
|
|
|
|
If ``auto_id`` is ``False``, then the form output will not include ``<label>``
|
|
tags nor ``id`` attributes::
|
|
|
|
>>> f = ContactForm(auto_id=False)
|
|
>>> print(f.as_table())
|
|
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required></td></tr>
|
|
<tr><th>Message:</th><td><input type="text" name="message" required></td></tr>
|
|
<tr><th>Sender:</th><td><input type="email" name="sender" required></td></tr>
|
|
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself"></td></tr>
|
|
>>> print(f.as_ul())
|
|
<li>Subject: <input type="text" name="subject" maxlength="100" required></li>
|
|
<li>Message: <input type="text" name="message" required></li>
|
|
<li>Sender: <input type="email" name="sender" required></li>
|
|
<li>Cc myself: <input type="checkbox" name="cc_myself"></li>
|
|
>>> print(f.as_p())
|
|
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
|
|
<p>Message: <input type="text" name="message" required></p>
|
|
<p>Sender: <input type="email" name="sender" required></p>
|
|
<p>Cc myself: <input type="checkbox" name="cc_myself"></p>
|
|
|
|
If ``auto_id`` is set to ``True``, then the form output *will* include
|
|
``<label>`` tags and will use the field name as its ``id`` for each form
|
|
field::
|
|
|
|
>>> f = ContactForm(auto_id=True)
|
|
>>> print(f.as_table())
|
|
<tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" required></td></tr>
|
|
<tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" required></td></tr>
|
|
<tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" required></td></tr>
|
|
<tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself"></td></tr>
|
|
>>> print(f.as_ul())
|
|
<li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required></li>
|
|
<li><label for="message">Message:</label> <input type="text" name="message" id="message" required></li>
|
|
<li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required></li>
|
|
<li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself"></li>
|
|
>>> print(f.as_p())
|
|
<p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" required></p>
|
|
<p><label for="message">Message:</label> <input type="text" name="message" id="message" required></p>
|
|
<p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" required></p>
|
|
<p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself"></p>
|
|
|
|
If ``auto_id`` is set to a string containing the format character ``'%s'``,
|
|
then the form output will include ``<label>`` tags, and will generate ``id``
|
|
attributes based on the format string. For example, for a format string
|
|
``'field_%s'``, a field named ``subject`` will get the ``id`` value
|
|
``'field_subject'``. Continuing our example::
|
|
|
|
>>> f = ContactForm(auto_id='id_for_%s')
|
|
>>> print(f.as_table())
|
|
<tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" required></td></tr>
|
|
<tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" required></td></tr>
|
|
<tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" required></td></tr>
|
|
<tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></td></tr>
|
|
>>> print(f.as_ul())
|
|
<li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
|
|
<li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required></li>
|
|
<li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required></li>
|
|
<li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
|
|
>>> print(f.as_p())
|
|
<p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></p>
|
|
<p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" required></p>
|
|
<p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" required></p>
|
|
<p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></p>
|
|
|
|
If ``auto_id`` is set to any other true value -- such as a string that doesn't
|
|
include ``%s`` -- then the library will act as if ``auto_id`` is ``True``.
|
|
|
|
By default, ``auto_id`` is set to the string ``'id_%s'``.
|
|
|
|
.. attribute:: Form.label_suffix
|
|
|
|
A translatable string (defaults to a colon (``:``) in English) that will be
|
|
appended after any label name when a form is rendered.
|
|
|
|
It's possible to customize that character, or omit it entirely, using the
|
|
``label_suffix`` parameter::
|
|
|
|
>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
|
|
>>> print(f.as_ul())
|
|
<li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
|
|
<li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" required></li>
|
|
<li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" required></li>
|
|
<li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
|
|
>>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
|
|
>>> print(f.as_ul())
|
|
<li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" required></li>
|
|
<li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" required></li>
|
|
<li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" required></li>
|
|
<li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself"></li>
|
|
|
|
Note that the label suffix is added only if the last character of the
|
|
label isn't a punctuation character (in English, those are ``.``, ``!``, ``?``
|
|
or ``:``).
|
|
|
|
Fields can also define their own :attr:`~django.forms.Field.label_suffix`.
|
|
This will take precedence over :attr:`Form.label_suffix
|
|
<django.forms.Form.label_suffix>`. The suffix can also be overridden at runtime
|
|
using the ``label_suffix`` parameter to
|
|
:meth:`~django.forms.BoundField.label_tag`.
|
|
|
|
.. attribute:: Form.use_required_attribute
|
|
|
|
When set to ``True`` (the default), required form fields will have the
|
|
``required`` HTML attribute.
|
|
|
|
:doc:`Formsets </topics/forms/formsets>` instantiate forms with
|
|
``use_required_attribute=False`` to avoid incorrect browser validation when
|
|
adding and deleting forms from a formset.
|
|
|
|
Configuring the rendering of a form's widgets
|
|
---------------------------------------------
|
|
|
|
.. attribute:: Form.default_renderer
|
|
|
|
Specifies the :doc:`renderer <renderers>` to use for the form. Defaults to
|
|
``None`` which means to use the default renderer specified by the
|
|
:setting:`FORM_RENDERER` setting.
|
|
|
|
You can set this as a class attribute when declaring your form or use the
|
|
``renderer`` argument to ``Form.__init__()``. For example::
|
|
|
|
from django import forms
|
|
|
|
class MyForm(forms.Form):
|
|
default_renderer = MyRenderer()
|
|
|
|
or::
|
|
|
|
form = MyForm(renderer=MyRenderer())
|
|
|
|
Notes on field ordering
|
|
-----------------------
|
|
|
|
In the ``as_p()``, ``as_ul()`` and ``as_table()`` shortcuts, the fields are
|
|
displayed in the order in which you define them in your form class. For
|
|
example, in the ``ContactForm`` example, the fields are defined in the order
|
|
``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML
|
|
output, change the order in which those fields are listed in the class.
|
|
|
|
There are several other ways to customize the order:
|
|
|
|
.. attribute:: Form.field_order
|
|
|
|
By default ``Form.field_order=None``, which retains the order in which you
|
|
define the fields in your form class. If ``field_order`` is a list of field
|
|
names, the fields are ordered as specified by the list and remaining fields are
|
|
appended according to the default order. Unknown field names in the list are
|
|
ignored. This makes it possible to disable a field in a subclass by setting it
|
|
to ``None`` without having to redefine ordering.
|
|
|
|
You can also use the ``Form.field_order`` argument to a :class:`Form` to
|
|
override the field order. If a :class:`~django.forms.Form` defines
|
|
:attr:`~Form.field_order` *and* you include ``field_order`` when instantiating
|
|
the ``Form``, then the latter ``field_order`` will have precedence.
|
|
|
|
.. method:: Form.order_fields(field_order)
|
|
|
|
You may rearrange the fields any time using ``order_fields()`` with a list of
|
|
field names as in :attr:`~django.forms.Form.field_order`.
|
|
|
|
How errors are displayed
|
|
------------------------
|
|
|
|
If you render a bound ``Form`` object, the act of rendering will automatically
|
|
run the form's validation if it hasn't already happened, and the HTML output
|
|
will include the validation errors as a ``<ul class="errorlist">`` near the
|
|
field. The particular positioning of the error messages depends on the output
|
|
method you're using::
|
|
|
|
>>> data = {'subject': '',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'invalid email address',
|
|
... 'cc_myself': True}
|
|
>>> f = ContactForm(data, auto_id=False)
|
|
>>> print(f.as_table())
|
|
<tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></td></tr>
|
|
<tr><th>Message:</th><td><input type="text" name="message" value="Hi there" required></td></tr>
|
|
<tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" required></td></tr>
|
|
<tr><th>Cc myself:</th><td><input checked type="checkbox" name="cc_myself"></td></tr>
|
|
>>> print(f.as_ul())
|
|
<li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" required></li>
|
|
<li>Message: <input type="text" name="message" value="Hi there" required></li>
|
|
<li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" required></li>
|
|
<li>Cc myself: <input checked type="checkbox" name="cc_myself"></li>
|
|
>>> print(f.as_p())
|
|
<p><ul class="errorlist"><li>This field is required.</li></ul></p>
|
|
<p>Subject: <input type="text" name="subject" maxlength="100" required></p>
|
|
<p>Message: <input type="text" name="message" value="Hi there" required></p>
|
|
<p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
|
|
<p>Sender: <input type="email" name="sender" value="invalid email address" required></p>
|
|
<p>Cc myself: <input checked type="checkbox" name="cc_myself"></p>
|
|
|
|
.. _ref-forms-error-list-format:
|
|
|
|
Customizing the error list format
|
|
---------------------------------
|
|
|
|
.. class:: ErrorList(initlist=None, error_class=None, renderer=None)
|
|
|
|
By default, forms use ``django.forms.utils.ErrorList`` to format validation
|
|
errors. ``ErrorList`` is a list like object where ``initlist`` is the
|
|
list of errors. In addition this class has the following attributes and
|
|
methods.
|
|
|
|
.. attribute:: error_class
|
|
|
|
The CSS classes to be used when rendering the error list. Any provided
|
|
classes are added to the default ``errorlist`` class.
|
|
|
|
.. attribute:: renderer
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
Specifies the :doc:`renderer <renderers>` to use for ``ErrorList``.
|
|
Defaults to ``None`` which means to use the default renderer
|
|
specified by the :setting:`FORM_RENDERER` setting.
|
|
|
|
.. attribute:: template_name
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
The name of the template used when calling ``__str__`` or
|
|
:meth:`render`. By default this is
|
|
``'django/forms/errors/list/default.html'`` which is a proxy for the
|
|
``'ul.html'`` template.
|
|
|
|
.. attribute:: template_name_text
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
The name of the template used when calling :meth:`.as_text`. By default
|
|
this is ``'django/forms/errors/list/text.html'``. This template renders
|
|
the errors as a list of bullet points.
|
|
|
|
.. attribute:: template_name_ul
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
The name of the template used when calling :meth:`.as_ul`. By default
|
|
this is ``'django/forms/errors/list/ul.html'``. This template renders
|
|
the errors in ``<li>`` tags with a wrapping ``<ul>`` with the CSS
|
|
classes as defined by :attr:`.error_class`.
|
|
|
|
.. method:: get_context()
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
Return context for rendering of errors in a template.
|
|
|
|
The available context is:
|
|
|
|
* ``errors`` : A list of the errors.
|
|
* ``error_class`` : A string of CSS classes.
|
|
|
|
.. method:: render(template_name=None, context=None, renderer=None)
|
|
|
|
.. versionadded:: 4.0
|
|
|
|
The render method is called by ``__str__`` as well as by the
|
|
:meth:`.as_ul` method.
|
|
|
|
All arguments are optional and will default to:
|
|
|
|
* ``template_name``: Value returned by :attr:`.template_name`
|
|
* ``context``: Value returned by :meth:`.get_context`
|
|
* ``renderer``: Value returned by :attr:`.renderer`
|
|
|
|
.. method:: as_text()
|
|
|
|
Renders the error list using the template defined by
|
|
:attr:`.template_name_text`.
|
|
|
|
.. method:: as_ul()
|
|
|
|
Renders the error list using the template defined by
|
|
:attr:`.template_name_ul`.
|
|
|
|
If you'd like to customize the rendering of errors this can be achieved by
|
|
overriding the :attr:`.template_name` attribute or more generally by
|
|
overriding the default template, see also
|
|
:ref:`overriding-built-in-form-templates`.
|
|
|
|
.. versionchanged:: 4.0
|
|
|
|
Rendering of :class:`ErrorList` was moved to the template engine.
|
|
|
|
.. deprecated:: 4.0
|
|
|
|
The ability to return a ``str`` when calling the ``__str__`` method is
|
|
deprecated. Use the template engine instead which returns a ``SafeString``.
|
|
|
|
More granular output
|
|
====================
|
|
|
|
The ``as_p()``, ``as_ul()``, and ``as_table()`` methods are shortcuts --
|
|
they're not the only way a form object can be displayed.
|
|
|
|
.. class:: BoundField
|
|
|
|
Used to display HTML or access attributes for a single field of a
|
|
:class:`Form` instance.
|
|
|
|
The ``__str__()`` method of this object displays the HTML for this field.
|
|
|
|
To retrieve a single ``BoundField``, use dictionary lookup syntax on your form
|
|
using the field's name as the key::
|
|
|
|
>>> form = ContactForm()
|
|
>>> print(form['subject'])
|
|
<input id="id_subject" type="text" name="subject" maxlength="100" required>
|
|
|
|
To retrieve all ``BoundField`` objects, iterate the form::
|
|
|
|
>>> form = ContactForm()
|
|
>>> for boundfield in form: print(boundfield)
|
|
<input id="id_subject" type="text" name="subject" maxlength="100" required>
|
|
<input type="text" name="message" id="id_message" required>
|
|
<input type="email" name="sender" id="id_sender" required>
|
|
<input type="checkbox" name="cc_myself" id="id_cc_myself">
|
|
|
|
The field-specific output honors the form object's ``auto_id`` setting::
|
|
|
|
>>> f = ContactForm(auto_id=False)
|
|
>>> print(f['message'])
|
|
<input type="text" name="message" required>
|
|
>>> f = ContactForm(auto_id='id_%s')
|
|
>>> print(f['message'])
|
|
<input type="text" name="message" id="id_message" required>
|
|
|
|
Attributes of ``BoundField``
|
|
----------------------------
|
|
|
|
.. attribute:: BoundField.auto_id
|
|
|
|
The HTML ID attribute for this ``BoundField``. Returns an empty string
|
|
if :attr:`Form.auto_id` is ``False``.
|
|
|
|
.. attribute:: BoundField.data
|
|
|
|
This property returns the data for this :class:`~django.forms.BoundField`
|
|
extracted by the widget's :meth:`~django.forms.Widget.value_from_datadict`
|
|
method, or ``None`` if it wasn't given::
|
|
|
|
>>> unbound_form = ContactForm()
|
|
>>> print(unbound_form['subject'].data)
|
|
None
|
|
>>> bound_form = ContactForm(data={'subject': 'My Subject'})
|
|
>>> print(bound_form['subject'].data)
|
|
My Subject
|
|
|
|
.. attribute:: BoundField.errors
|
|
|
|
A :ref:`list-like object <ref-forms-error-list-format>` that is displayed
|
|
as an HTML ``<ul class="errorlist">`` when printed::
|
|
|
|
>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
|
|
>>> f = ContactForm(data, auto_id=False)
|
|
>>> print(f['message'])
|
|
<input type="text" name="message" required>
|
|
>>> f['message'].errors
|
|
['This field is required.']
|
|
>>> print(f['message'].errors)
|
|
<ul class="errorlist"><li>This field is required.</li></ul>
|
|
>>> f['subject'].errors
|
|
[]
|
|
>>> print(f['subject'].errors)
|
|
|
|
>>> str(f['subject'].errors)
|
|
''
|
|
|
|
.. attribute:: BoundField.field
|
|
|
|
The form :class:`~django.forms.Field` instance from the form class that
|
|
this :class:`~django.forms.BoundField` wraps.
|
|
|
|
.. attribute:: BoundField.form
|
|
|
|
The :class:`~django.forms.Form` instance this :class:`~django.forms.BoundField`
|
|
is bound to.
|
|
|
|
.. attribute:: BoundField.help_text
|
|
|
|
The :attr:`~django.forms.Field.help_text` of the field.
|
|
|
|
.. attribute:: BoundField.html_name
|
|
|
|
The name that will be used in the widget's HTML ``name`` attribute. It takes
|
|
the form :attr:`~django.forms.Form.prefix` into account.
|
|
|
|
.. attribute:: BoundField.id_for_label
|
|
|
|
Use this property to render the ID of this field. For example, if you are
|
|
manually constructing a ``<label>`` in your template (despite the fact that
|
|
:meth:`~BoundField.label_tag` will do this for you):
|
|
|
|
.. code-block:: html+django
|
|
|
|
<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}
|
|
|
|
By default, this will be the field's name prefixed by ``id_``
|
|
("``id_my_field``" for the example above). You may modify the ID by setting
|
|
:attr:`~django.forms.Widget.attrs` on the field's widget. For example,
|
|
declaring a field like this::
|
|
|
|
my_field = forms.CharField(widget=forms.TextInput(attrs={'id': 'myFIELD'}))
|
|
|
|
and using the template above, would render something like:
|
|
|
|
.. code-block:: html
|
|
|
|
<label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" required>
|
|
|
|
.. attribute:: BoundField.initial
|
|
|
|
Use :attr:`BoundField.initial` to retrieve initial data for a form field.
|
|
It retrieves the data from :attr:`Form.initial` if present, otherwise
|
|
trying :attr:`Field.initial`. Callable values are evaluated. See
|
|
:ref:`ref-forms-initial-form-values` for more examples.
|
|
|
|
:attr:`BoundField.initial` caches its return value, which is useful
|
|
especially when dealing with callables whose return values can change (e.g.
|
|
``datetime.now`` or ``uuid.uuid4``)::
|
|
|
|
>>> from datetime import datetime
|
|
>>> class DatedCommentForm(CommentForm):
|
|
... created = forms.DateTimeField(initial=datetime.now)
|
|
>>> f = DatedCommentForm()
|
|
>>> f['created'].initial
|
|
datetime.datetime(2021, 7, 27, 9, 5, 54)
|
|
>>> f['created'].initial
|
|
datetime.datetime(2021, 7, 27, 9, 5, 54)
|
|
|
|
Using :attr:`BoundField.initial` is recommended over
|
|
:meth:`~Form.get_initial_for_field()`.
|
|
|
|
.. attribute:: BoundField.is_hidden
|
|
|
|
Returns ``True`` if this :class:`~django.forms.BoundField`'s widget is
|
|
hidden.
|
|
|
|
.. attribute:: BoundField.label
|
|
|
|
The :attr:`~django.forms.Field.label` of the field. This is used in
|
|
:meth:`~BoundField.label_tag`.
|
|
|
|
.. attribute:: BoundField.name
|
|
|
|
The name of this field in the form::
|
|
|
|
>>> f = ContactForm()
|
|
>>> print(f['subject'].name)
|
|
subject
|
|
>>> print(f['message'].name)
|
|
message
|
|
|
|
.. attribute:: BoundField.widget_type
|
|
|
|
Returns the lowercased class name of the wrapped field's widget, with any
|
|
trailing ``input`` or ``widget`` removed. This may be used when building
|
|
forms where the layout is dependent upon the widget type. For example::
|
|
|
|
{% for field in form %}
|
|
{% if field.widget_type == 'checkbox' %}
|
|
# render one way
|
|
{% else %}
|
|
# render another way
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
|
|
Methods of ``BoundField``
|
|
-------------------------
|
|
|
|
.. method:: BoundField.as_hidden(attrs=None, **kwargs)
|
|
|
|
Returns a string of HTML for representing this as an ``<input type="hidden">``.
|
|
|
|
``**kwargs`` are passed to :meth:`~django.forms.BoundField.as_widget`.
|
|
|
|
This method is primarily used internally. You should use a widget instead.
|
|
|
|
.. method:: BoundField.as_widget(widget=None, attrs=None, only_initial=False)
|
|
|
|
Renders the field by rendering the passed widget, adding any HTML
|
|
attributes passed as ``attrs``. If no widget is specified, then the
|
|
field's default widget will be used.
|
|
|
|
``only_initial`` is used by Django internals and should not be set
|
|
explicitly.
|
|
|
|
.. method:: BoundField.css_classes(extra_classes=None)
|
|
|
|
When you use Django's rendering shortcuts, CSS classes are used to
|
|
indicate required form fields or fields that contain errors. If you're
|
|
manually rendering a form, you can access these CSS classes using the
|
|
``css_classes`` method::
|
|
|
|
>>> f = ContactForm(data={'message': ''})
|
|
>>> f['message'].css_classes()
|
|
'required'
|
|
|
|
If you want to provide some additional classes in addition to the
|
|
error and required classes that may be required, you can provide
|
|
those classes as an argument::
|
|
|
|
>>> f = ContactForm(data={'message': ''})
|
|
>>> f['message'].css_classes('foo bar')
|
|
'foo bar required'
|
|
|
|
.. method:: BoundField.label_tag(contents=None, attrs=None, label_suffix=None)
|
|
|
|
To separately render the label tag of a form field, you can call its
|
|
``label_tag()`` method::
|
|
|
|
>>> f = ContactForm(data={'message': ''})
|
|
>>> print(f['message'].label_tag())
|
|
<label for="id_message">Message:</label>
|
|
|
|
You can provide the ``contents`` parameter which will replace the
|
|
auto-generated label tag. An ``attrs`` dictionary may contain additional
|
|
attributes for the ``<label>`` tag.
|
|
|
|
The HTML that's generated includes the form's
|
|
:attr:`~django.forms.Form.label_suffix` (a colon, by default) or, if set,
|
|
the current field's :attr:`~django.forms.Field.label_suffix`. The optional
|
|
``label_suffix`` parameter allows you to override any previously set
|
|
suffix. For example, you can use an empty string to hide the label on
|
|
selected fields. The label is rendered using the template specified by the
|
|
forms :attr:`.Form.template_name_label`.
|
|
|
|
.. versionchanged:: 4.0
|
|
|
|
The label is now rendered using the template engine.
|
|
|
|
.. method:: BoundField.value()
|
|
|
|
Use this method to render the raw value of this field as it would be rendered
|
|
by a ``Widget``::
|
|
|
|
>>> initial = {'subject': 'welcome'}
|
|
>>> unbound_form = ContactForm(initial=initial)
|
|
>>> bound_form = ContactForm(data={'subject': 'hi'}, initial=initial)
|
|
>>> print(unbound_form['subject'].value())
|
|
welcome
|
|
>>> print(bound_form['subject'].value())
|
|
hi
|
|
|
|
Customizing ``BoundField``
|
|
==========================
|
|
|
|
If you need to access some additional information about a form field in a
|
|
template and using a subclass of :class:`~django.forms.Field` isn't
|
|
sufficient, consider also customizing :class:`~django.forms.BoundField`.
|
|
|
|
A custom form field can override ``get_bound_field()``:
|
|
|
|
.. method:: Field.get_bound_field(form, field_name)
|
|
|
|
Takes an instance of :class:`~django.forms.Form` and the name of the field.
|
|
The return value will be used when accessing the field in a template. Most
|
|
likely it will be an instance of a subclass of
|
|
:class:`~django.forms.BoundField`.
|
|
|
|
If you have a ``GPSCoordinatesField``, for example, and want to be able to
|
|
access additional information about the coordinates in a template, this could
|
|
be implemented as follows::
|
|
|
|
class GPSCoordinatesBoundField(BoundField):
|
|
@property
|
|
def country(self):
|
|
"""
|
|
Return the country the coordinates lie in or None if it can't be
|
|
determined.
|
|
"""
|
|
value = self.value()
|
|
if value:
|
|
return get_country_from_coordinates(value)
|
|
else:
|
|
return None
|
|
|
|
class GPSCoordinatesField(Field):
|
|
def get_bound_field(self, form, field_name):
|
|
return GPSCoordinatesBoundField(form, self, field_name)
|
|
|
|
Now you can access the country in a template with
|
|
``{{ form.coordinates.country }}``.
|
|
|
|
.. _binding-uploaded-files:
|
|
|
|
Binding uploaded files to a form
|
|
================================
|
|
|
|
Dealing with forms that have ``FileField`` and ``ImageField`` fields
|
|
is a little more complicated than a normal form.
|
|
|
|
Firstly, in order to upload files, you'll need to make sure that your
|
|
``<form>`` element correctly defines the ``enctype`` as
|
|
``"multipart/form-data"``::
|
|
|
|
<form enctype="multipart/form-data" method="post" action="/foo/">
|
|
|
|
Secondly, when you use the form, you need to bind the file data. File
|
|
data is handled separately to normal form data, so when your form
|
|
contains a ``FileField`` and ``ImageField``, you will need to specify
|
|
a second argument when you bind your form. So if we extend our
|
|
ContactForm to include an ``ImageField`` called ``mugshot``, we
|
|
need to bind the file data containing the mugshot image::
|
|
|
|
# Bound form with an image field
|
|
>>> from django.core.files.uploadedfile import SimpleUploadedFile
|
|
>>> data = {'subject': 'hello',
|
|
... 'message': 'Hi there',
|
|
... 'sender': 'foo@example.com',
|
|
... 'cc_myself': True}
|
|
>>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)}
|
|
>>> f = ContactFormWithMugshot(data, file_data)
|
|
|
|
In practice, you will usually specify ``request.FILES`` as the source
|
|
of file data (just like you use ``request.POST`` as the source of
|
|
form data)::
|
|
|
|
# Bound form with an image field, data from the request
|
|
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
|
|
|
|
Constructing an unbound form is the same as always -- omit both form data *and*
|
|
file data::
|
|
|
|
# Unbound form with an image field
|
|
>>> f = ContactFormWithMugshot()
|
|
|
|
Testing for multipart forms
|
|
---------------------------
|
|
|
|
.. method:: Form.is_multipart()
|
|
|
|
If you're writing reusable views or templates, you may not know ahead of time
|
|
whether your form is a multipart form or not. The ``is_multipart()`` method
|
|
tells you whether the form requires multipart encoding for submission::
|
|
|
|
>>> f = ContactFormWithMugshot()
|
|
>>> f.is_multipart()
|
|
True
|
|
|
|
Here's an example of how you might use this in a template::
|
|
|
|
{% if form.is_multipart %}
|
|
<form enctype="multipart/form-data" method="post" action="/foo/">
|
|
{% else %}
|
|
<form method="post" action="/foo/">
|
|
{% endif %}
|
|
{{ form }}
|
|
</form>
|
|
|
|
Subclassing forms
|
|
=================
|
|
|
|
If you have multiple ``Form`` classes that share fields, you can use
|
|
subclassing to remove redundancy.
|
|
|
|
When you subclass a custom ``Form`` class, the resulting subclass will
|
|
include all fields of the parent class(es), followed by the fields you define
|
|
in the subclass.
|
|
|
|
In this example, ``ContactFormWithPriority`` contains all the fields from
|
|
``ContactForm``, plus an additional field, ``priority``. The ``ContactForm``
|
|
fields are ordered first::
|
|
|
|
>>> class ContactFormWithPriority(ContactForm):
|
|
... priority = forms.CharField()
|
|
>>> f = ContactFormWithPriority(auto_id=False)
|
|
>>> print(f.as_ul())
|
|
<li>Subject: <input type="text" name="subject" maxlength="100" required></li>
|
|
<li>Message: <input type="text" name="message" required></li>
|
|
<li>Sender: <input type="email" name="sender" required></li>
|
|
<li>Cc myself: <input type="checkbox" name="cc_myself"></li>
|
|
<li>Priority: <input type="text" name="priority" required></li>
|
|
|
|
It's possible to subclass multiple forms, treating forms as mixins. In this
|
|
example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
|
|
(in that order), and its field list includes the fields from the parent
|
|
classes::
|
|
|
|
>>> from django import forms
|
|
>>> class PersonForm(forms.Form):
|
|
... first_name = forms.CharField()
|
|
... last_name = forms.CharField()
|
|
>>> class InstrumentForm(forms.Form):
|
|
... instrument = forms.CharField()
|
|
>>> class BeatleForm(InstrumentForm, PersonForm):
|
|
... haircut_type = forms.CharField()
|
|
>>> b = BeatleForm(auto_id=False)
|
|
>>> print(b.as_ul())
|
|
<li>First name: <input type="text" name="first_name" required></li>
|
|
<li>Last name: <input type="text" name="last_name" required></li>
|
|
<li>Instrument: <input type="text" name="instrument" required></li>
|
|
<li>Haircut type: <input type="text" name="haircut_type" required></li>
|
|
|
|
It's possible to declaratively remove a ``Field`` inherited from a parent class
|
|
by setting the name of the field to ``None`` on the subclass. For example::
|
|
|
|
>>> from django import forms
|
|
|
|
>>> class ParentForm(forms.Form):
|
|
... name = forms.CharField()
|
|
... age = forms.IntegerField()
|
|
|
|
>>> class ChildForm(ParentForm):
|
|
... name = None
|
|
|
|
>>> list(ChildForm().fields)
|
|
['age']
|
|
|
|
.. _form-prefix:
|
|
|
|
Prefixes for forms
|
|
==================
|
|
|
|
.. attribute:: Form.prefix
|
|
|
|
You can put several Django forms inside one ``<form>`` tag. To give each
|
|
``Form`` its own namespace, use the ``prefix`` keyword argument::
|
|
|
|
>>> mother = PersonForm(prefix="mother")
|
|
>>> father = PersonForm(prefix="father")
|
|
>>> print(mother.as_ul())
|
|
<li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" required></li>
|
|
<li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" required></li>
|
|
>>> print(father.as_ul())
|
|
<li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" required></li>
|
|
<li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" required></li>
|
|
|
|
The prefix can also be specified on the form class::
|
|
|
|
>>> class PersonForm(forms.Form):
|
|
... ...
|
|
... prefix = 'person'
|