Removed Form._errors from the docs in favor of the add_error API.

This commit is contained in:
Loic Bistuer 2013-11-12 21:18:09 +07:00
parent f563c339ca
commit b72b85af15
2 changed files with 11 additions and 95 deletions

View File

@ -123,8 +123,7 @@ if validation has side effects, those side effects will only be triggered once.
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. This is a better alternative to fiddling directly with
``Form._errors`` as described in :ref:`modifying-field-errors`.
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

View File

@ -86,9 +86,8 @@ overridden:
be associated with any field in particular. They go into a special
"field" (called ``__all__``), which you can access via the
``non_field_errors()`` method if you need to. If you want to attach
errors to a specific field in the form, you will need to access the
``_errors`` attribute on the form, which is
:ref:`described later <modifying-field-errors>`.
errors to a specific field in the form, you need to call
:meth:`~django.forms.Form.add_error()`.
Also note that there are special considerations when overriding
the ``clean()`` method of a ``ModelForm`` subclass. (see the
@ -202,52 +201,6 @@ with ``code``\s and ``params`` but a list of strings will also work::
_('Error 2'),
])
.. _modifying-field-errors:
Form subclasses and modifying field errors
------------------------------------------
Sometimes, in a form's ``clean()`` method, you will want to add an error
message to a particular field in the form. This won't always be appropriate
and the more typical situation is to raise a ``ValidationError`` from
``Form.clean()``, which is turned into a form-wide error that is available
through the ``Form.non_field_errors()`` method.
When you really do need to attach the error to a particular field, you should
store (or amend) a key in the ``Form._errors`` attribute. This attribute is an
instance of a ``django.forms.utils.ErrorDict`` class. Essentially, though, it's
just a dictionary. There is a key in the dictionary for each field in the form
that has an error. Each value in the dictionary is a
``django.forms.utils.ErrorList`` instance, which is a list that knows how to
display itself in different ways. So you can treat ``_errors`` as a dictionary
mapping field names to lists.
If you want to add a new error to a particular field, you should check whether
the key already exists in ``self._errors`` or not. If not, create a new entry
for the given key, holding an empty ``ErrorList`` instance. In either case,
you can then append your error message to the list for the field name in
question and it will be displayed when the form is displayed.
There is an example of modifying ``self._errors`` in the following section.
.. admonition:: What's in a name?
You may be wondering why is this attribute called ``_errors`` and not
``errors``. Normal Python practice is to prefix a name with an underscore
if it's not for external usage. In this case, you are subclassing the
``Form`` class, so you are essentially writing new internals. In effect,
you are given permission to access some of the internals of ``Form``.
Of course, any code outside your form should never access ``_errors``
directly. The data is available to external code through the ``errors``
property, which populates ``_errors`` before returning it).
Another reason is purely historical: the attribute has been called
``_errors`` since the early days of the forms module and changing it now
(particularly since ``errors`` is used for the read-only property name)
would be inconvenient for a number of reasons. You can use whichever
explanation makes you feel more comfortable. The result is the same.
Using validation in practice
----------------------------
@ -366,6 +319,13 @@ write a cleaning method that operates on the ``recipients`` field, like so::
# not.
return data
Sometimes you may want to add an error message to a particular field from the
form's ``clean()`` method, in which case you can use
:meth:`~django.forms.Form.add_error()`. Note that this won't always be
appropriate and the more typical situation is to raise a ``ValidationError``
from , which is turned into a form-wide error that is available through the
``Form.non_field_errors()`` method.
Cleaning and validating fields that depend on each other
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -431,47 +391,6 @@ sample) looks like this::
from django import forms
class ContactForm(forms.Form):
# Everything as before.
...
def clean(self):
cleaned_data = super(ContactForm, self).clean()
cc_myself = cleaned_data.get("cc_myself")
subject = cleaned_data.get("subject")
if cc_myself and subject and "help" not in subject:
# We know these are not in self._errors now (see discussion
# below).
msg = u"Must put 'help' in subject when cc'ing yourself."
self._errors["cc_myself"] = self.error_class([msg])
self._errors["subject"] = self.error_class([msg])
# These fields are no longer valid. Remove them from the
# cleaned data.
del cleaned_data["cc_myself"]
del cleaned_data["subject"]
As you can see, this approach requires a bit more effort, not withstanding the
extra design effort to create a sensible form display. The details are worth
noting, however. Firstly, earlier we mentioned that you might need to check if
the field name keys already exist in the ``_errors`` dictionary. In this case,
since we know the fields exist in ``self.cleaned_data``, they must have been
valid when cleaned as individual fields, so there will be no corresponding
entries in ``_errors``.
Secondly, once we have decided that the combined data in the two fields we are
considering aren't valid, we must remember to remove them from the
``cleaned_data``. `cleaned_data`` is present even if the form doesn't
validate, but it contains only field values that did validate.
.. versionchanged:: 1.7
In lieu of manipulating ``_errors`` directly, it's now possible to add errors
to specific fields with :meth:`django.forms.Form.add_error()`::
from django import forms
class ContactForm(forms.Form):
# Everything as before.
...
@ -488,7 +407,5 @@ to specific fields with :meth:`django.forms.Form.add_error()`::
The second argument of ``add_error()`` can be a simple string, or preferably
an instance of ``ValidationError``. See :ref:`raising-validation-error` for
more details.
Unlike the ``_errors`` approach, ``add_error()` automatically removes the field
more details. Note that ``add_error()` automatically removes the field
from ``cleaned_data``.