From b72b85af153848ef5f1f07f5c1e5a81e3563b015 Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Tue, 12 Nov 2013 21:18:09 +0700 Subject: [PATCH] Removed Form._errors from the docs in favor of the add_error API. --- docs/ref/forms/api.txt | 3 +- docs/ref/forms/validation.txt | 103 ++++------------------------------ 2 files changed, 11 insertions(+), 95 deletions(-) diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index c06a836bef..69667643b4 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -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 diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt index 3c7715dfcb..a07cb93183 100644 --- a/docs/ref/forms/validation.txt +++ b/docs/ref/forms/validation.txt @@ -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 `. + 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``.