diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/forms/fields.txt | 11 | ||||
| -rw-r--r-- | docs/ref/forms/validation.txt | 111 | ||||
| -rw-r--r-- | docs/ref/models/fields.txt | 22 | ||||
| -rw-r--r-- | docs/ref/models/instances.txt | 25 |
4 files changed, 144 insertions, 25 deletions
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt index 4bb6a7c444..0d40e5fd5f 100644 --- a/docs/ref/forms/fields.txt +++ b/docs/ref/forms/fields.txt @@ -257,6 +257,17 @@ And here is a custom error message:: In the `built-in Field classes`_ section below, each ``Field`` defines the error message keys it uses. +``validators`` +~~~~~~~~~~~~~~ +.. versionadded:: 1.2 + +.. attribute:: Field.validators + +The ``validators`` argument lets you provide a list of validation functions +for this field. + +See the :ref:`validators documentation <validators>` for more information. + Built-in ``Field`` classes -------------------------- diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt index 6f5041f699..b6642d5253 100644 --- a/docs/ref/forms/validation.txt +++ b/docs/ref/forms/validation.txt @@ -3,6 +3,8 @@ Form and field validation ========================= +.. versionchanged:: 1.2 + Form validation happens when the data is cleaned. If you want to customize this process, there are various places you can change, each one serving a different purpose. Three types of cleaning methods are run during form @@ -20,13 +22,38 @@ If you detect multiple errors during a cleaning method and wish to signal all of them to the form submitter, it is possible to pass a list of errors to the ``ValidationError`` constructor. -The three types of cleaning methods are: +Most validation can be done using `validators`_ - simple helpers that can be +reused easily. Validators are simple functions (or callables) that take a single +argument and raise ``ValidationError`` on invalid input. Validators are run +after the field's ``to_python`` and ``validate`` methods have been called. + +Validation of a Form is split into several steps, which can be customized or +overridden: + + * The ``to_python()`` method on a Field is the first step in every + validation. It coerces the value to correct datatype and raises + ``ValidationError`` if that is not possible. This method accepts the raw + value from the widget and returns the converted value. For example, a + FloatField will turn the data into a Python ``float`` or raise a + ``ValidationError``. + + * The ``validate()`` method on a Field handles field-specific validation + that is not suitable for a validator, It takes a value that has been + coerced to correct datatype and raises ``ValidationError`` on any error. + This method does not return anything and shouldn't alter the value. You + should override it to handle validation logic that you can't or don't + want to put in a validator. + + * The ``run_validators()`` method on a Field runs all of the field's + validators and aggregates all the errors into a single + ``ValidationError``. You shouldn't need to override this method. - * The ``clean()`` method on a Field subclass. This is responsible - for cleaning the data in a way that is generic for that type of field. - For example, a FloatField will turn the data into a Python ``float`` or - raise a ``ValidationError``. This method returns the clean data, which - is then inserted into the ``cleaned_data`` dictionary of the form. + * The ``clean()`` method on a Field subclass. This is responsible for + running ``to_python``, ``validate`` and ``run_validators`` in the correct + order and propagating their errors. If, at any time, any of the methods + raise ``ValidationError``, the validation stops and that error is raised. + This method returns the clean data, which is then inserted into the + ``cleaned_data`` dictionary of the form. * The ``clean_<fieldname>()`` method in a form subclass -- where ``<fieldname>`` is replaced with the name of the form field attribute. @@ -141,35 +168,68 @@ Since it can sometimes be easier to put things into place by seeing each feature in use, here are a series of small examples that use each of the previous features. +.. _validators: + +Using validators +~~~~~~~~~~~~~~~~ +.. versionadded:: 1.2 + +Django's form (and model) fields support use of simple utility functions and +classes known as validators. These can passed to a field's constructor, via +the field's ``validators`` argument, or defined on the Field class itself with +the ``default_validators`` attribute. + +Simple validators can be used to validate values inside the field, let's have +a look at Django's ``EmailField``:: + + class EmailField(CharField): + default_error_messages = { + 'invalid': _(u'Enter a valid e-mail address.'), + } + default_validators = [validators.validate_email] + +As you can see, ``EmailField`` is just a ``CharField`` with customized error +message and a validator that validates e-mail addresses. This can also be done +on field definition so:: + + email = forms.EmailField() + +is equivalent to:: + + email = forms.CharField(validators=[validators.validate_email], + error_messages={'invalid': _(u'Enter a valid e-mail address.')}) + + Form field default cleaning ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Let's firstly create a custom form field that validates its input is a string -containing comma-separated e-mail addresses, with at least one address. We'll -keep it simple and assume e-mail validation is contained in a function called -``is_valid_email()``. The full class looks like this:: +containing comma-separated e-mail addresses. The full class looks like this:: from django import forms + from django.core.validators import validate_email class MultiEmailField(forms.Field): - def clean(self, value): - """ - Check that the field contains one or more comma-separated emails - and normalizes the data to a list of the email strings. - """ + def to_python(self, value): + "Normalize data to a list of strings." + + # Return an empty list if no input was given. if not value: - raise forms.ValidationError('Enter at least one e-mail address.') - emails = value.split(',') - for email in emails: - if not is_valid_email(email): - raise forms.ValidationError('%s is not a valid e-mail address.' % email) + return [] + return value.split(',') + + def validate(self, value): + "Check if value consists only of valid emails." + + # Use the parent's handling of required fields, etc. + super(MultiEmailField, self).validate(value) - # Always return the cleaned data. - return emails + for email in value: + validate_email(email) -Every form that uses this field will have this ``clean()`` method run before -anything else can be done with the field's data. This is cleaning that is -specific to this type of field, regardless of how it is subsequently used. +Every form that uses this field will have these methods run before anything +else can be done with the field's data. This is cleaning that is specific to +this type of field, regardless of how it is subsequently used. Let's create a simple ``ContactForm`` to demonstrate how you'd use this field:: @@ -183,7 +243,8 @@ field:: Simply use ``MultiEmailField`` like any other form field. When the ``is_valid()`` method is called on the form, the ``MultiEmailField.clean()`` -method will be run as part of the cleaning process. +method will be run as part of the cleaning process and it will, in turn, call +the custom ``to_python()`` and ``validate()`` methods. Cleaning a specific field attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index 3c1106a217..8612b742ef 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -196,6 +196,17 @@ callable it will be called every time a new object is created. If ``False``, the field will not be editable in the admin or via forms automatically generated from the model class. Default is ``True``. +``error_messages`` +------------------ + +.. versionadded:: 1.2 + +.. attribute:: Field.error_messages + +The ``error_messages`` argument lets you override the default messages that the +field will raise. Pass in a dictionary with keys matching the error messages you +want to override. + ``help_text`` ------------- @@ -284,6 +295,17 @@ underscores to spaces. See :ref:`Verbose field names <verbose-field-names>`. .. _model-field-types: +``validators`` +------------------- + +.. versionadded:: 1.2 + +.. attribute:: Field.validators + +A list of validators to run for this field.See the :ref:`validators +documentation <validators>` for more information. + + Field types =========== diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index 7a0606dafe..43f18338a1 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -27,6 +27,31 @@ The keyword arguments are simply the names of the fields you've defined on your model. Note that instantiating a model in no way touches your database; for that, you need to ``save()``. +Validating objects +================== + +.. versionadded:: 1.2 + +To validate your model, just call its ``full_validate()`` method: + +.. method:: Model.full_validate([exclude=[]]) + +The optional ``exclude`` argument can contain a list of field names that should +be omitted when validating. This method raises ``ValidationError`` containing a +message dict with errors from all fields. + +To add your own validation logic, override the supplied ``validate()`` method: + +.. method:: Model.validate() + +The ``validate()`` method on ``Model`` by default checks for uniqueness of +fields and group of fields that are declared to be unique so, remember to call +``self.validate_unique()`` or the superclasses ``validate`` method if you want +this validation to run. + +Any ``ValidationError`` raised in this method will be propagated in the +``message_dict`` under ``NON_FIELD_ERRORS``. + Saving objects ============== |
