Loading docs/ref/forms/api.txt +1 −2 Original line number Diff line number Diff line Loading @@ -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 Loading docs/ref/forms/validation.txt +10 −93 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 ---------------------------- Loading Loading @@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Loading Loading @@ -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. ... Loading @@ -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``. Loading
docs/ref/forms/api.txt +1 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
docs/ref/forms/validation.txt +10 −93 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 ---------------------------- Loading Loading @@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Loading Loading @@ -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. ... Loading @@ -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``.