Commits

jkoc...@bcc190cf-cafb-0310-a4f2-bffc1f526a37  committed c6e1fd7

[soc2009/model-validation] Removed references in the docs to ComplexValidator. Refs [12498].

  • Participants
  • Parent commits fc807c1
  • Branches soc2009/model-validation

Comments (0)

Files changed (1)

File docs/ref/forms/validation.txt

 ``ValidationError`` constructor.
 
 Most validation can be done using `validators`_ - simple helpers that can be
-reused easily. There are two types of validators:
-
-    * Simple validators are simple functions (or callables) that take a single
-      argument and raises ``ValidationError`` on invalid input.  Simple
-      validators are run inside the ``run_validators`` method that is called
-      from ``Field.clean`` once the value is validated by the field's methods.
-
-    * Complex validators are instances of ``ComplexValidator`` class and,
-      unlike simple validators, can access not just one value, but all at once.
-      These are perfectly suited for cross field validation (one of N fields
-      must be supplied, this field must equal that etc.)
-
-
-.. warning::
-
-    Since complex validators must have access to all cleaned values, they must
-    be run after individual fields have been cleaned. This means that these are run
-    in ``Form.full_clean`` and not inside ``Field.clean`` with simple validators.
-
+reused easily. Validators are simple functions (or callables) that take a single
+argument and raise ``ValidationError`` on invalid input. Validators are run
+inside the ``run_validators`` method that is called from ``Field.clean`` once
+the value is validated by the field's methods.
 
 Validation of a Form is split into several steps, which can be customized or
 overridden:
       raises ``ValidationError`` on any error. This method does not return
       anything and shouldn't alter the value.
 
-    * Simple validators are run in the ``run_validators`` method. This method
+    * Validators are run in the ``run_validators`` method. This method
       aggregates all the errors from all validators run into a single
       ``ValidationError``.
-    
+
     * The ``clean()`` method on a Field subclass. This is responsible for
       running ``to_python``, ``validate`` and ``run_validators`` in the correct
       order and propagate their errors. If, at any time, any of the methods
       should return the cleaned data, regardless of whether it changed
       anything or not.
 
-    * The Field's complex validators are run after all the fields have been
-      cleaned and only on those fields that passed validation. Errors from
-      individual validators are aggregated and all the errors are raised for a
-      given field.
-
     * The Form subclass's ``clean()`` method. This method can perform
       any validation that requires access to multiple fields from the form at
       once. This is where you might put in things to check that if field ``A``
 These methods are run in the order given above, one field at a time.  That is,
 for each field in the form (in the order they are declared in the form
 definition), the ``Field.clean()`` method (or its override) is run, then
-``clean_<fieldname>()``. Once those two methods are run for every
-field, the complex validators are run for every field and, finally,
-``Form.clean()`` method, or its override, is executed.
+``clean_<fieldname>()``. Finally, once those two methods are run for every
+field, the ``Form.clean()`` method, or its override, is executed.
 
 Examples of each of these methods are provided below.
 
 
 Suppose we add another requirement to our contact form: if the ``cc_myself``
 field is ``True``, the ``subject`` must contain the word ``"help"``. We are
-performing validation on more than one field at a time, so a
-``ComplexValidator`` is a good start. The complex validators are run in the
-form's ``clean()`` after the individual fields have been validated. This is the
-main difference against simple validators. It is important to realize that,
-even if defined in very similar way, simple and complex validators are run in
-different places in the code. Simple validators on a field (single data point),
-complex validator on a form (collection of fields).
+performing validation on more than one field at a time, so the form's
+``clean()`` method is a good spot to do this. Notice that we are talking about
+the ``clean()`` method on the form here, whereas earlier we were writing a
+``clean()`` method on a field. It's important to keep the field and form
+difference clear when working out where to validate things. Fields are single
+data points, forms are a collection of fields.
 
-By the time the field's complex validators are called, all the individual field
-clean methods will have been run (the previous two sections), so the
-validator's ``all_values`` argument will be populated with any data that has
-survived so far. So you also need to remember to allow for the fact that the
-fields you are wanting to validate might not have survived the initial
-individual field checks.
+By the time the form's ``clean()`` method is called, all the individual field
+clean methods will have been run (the previous two sections), so
+``self.cleaned_data`` will be populated with any data that has survived so
+far. So you also need to remember to allow for the fact that the fields you
+are wanting to validate might not have survived the initial individual field
+checks.
 
-Complex validator is run on the form, but reports it's error with the field. As
-with simple validators, all complex validators for a given field are run if the
-field has passed cleaning and their errors are aggregated and reported.
-
-To create a complex validator, simply subclass ``ComplexValidator`` and supply
-your validation logic in it's ``__call__()`` method, for example::
-
-    class ValidateHelpInSubjectIfCCingMyself(ComplexValidator):
-        def __call__(self, all_values={}, obj=None):
-            cc_myself = self.get_value('cc_myself', all_values, obj)
-
-            if cc_myself and "help" not in value:
-                raise forms.ValidationError("Did not send for 'help' in "
-                        "the subject despite CC'ing yourself.")
-                
+There are two way to report any errors from this step. Probably the most
+common method is to display the error at the top of the form. To create such
+an error, you can raise a ``ValidationError`` from the ``clean()`` method. For
+example::
 
     class ContactForm(forms.Form):
-        subject = forms.CharField(max_length=100,
-            validators=[ValidateHelpInSubjectIfCCingMyself()])
+        # Everything as before.
         ...
-        # Everything as before.
 
+        def clean(self):
+            cleaned_data = self.cleaned_data
+            cc_myself = cleaned_data.get("cc_myself")
+            subject = cleaned_data.get("subject")
 
-The second approach might involve assigning the error message to both fields
-involved. To do this we will move the validation code to the form's ``clean()``
-method, which is a convenient place for form-wide validation and has access to
-the form instance and it's ``_errors`` property. Our new code (replacing the
-previous sample) looks like this::
+            if cc_myself and subject:
+                # Only do something if both fields are valid so far.
+                if "help" not in subject:
+                    raise forms.ValidationError("Did not send for 'help' in "
+                            "the subject despite CC'ing yourself.")
+
+            # Always return the full collection of cleaned data.
+            return cleaned_data
+
+In this code, if the validation error is raised, the form will display an
+error message at the top of the form (normally) describing the problem.
+
+The second approach might involve assigning the error message to one of the
+fields. In this case, let's assign an error message to both the "subject" and
+"cc_myself" rows in the form display. Be careful when doing this in practice,
+since it can lead to confusing form output. We're showing what is possible
+here and leaving it up to you and your designers to work out what works
+effectively in your particular situation. Our new code (replacing the previous
+sample) looks like this::
 
     from django.forms.util import ErrorList