mirror of
https://github.com/django/django.git
synced 2025-08-04 10:59:45 +00:00
Merged soc2009/model-validation to trunk. Thanks, Honza!
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12098 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4e89105d64
commit
471596fc1a
63 changed files with 1550 additions and 639 deletions
|
@ -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
|
||||
--------------------------
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
* 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.
|
||||
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
|
||||
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(',')
|
||||
|
||||
# Always return the cleaned data.
|
||||
return emails
|
||||
def validate(self, value):
|
||||
"Check if value consists only of valid emails."
|
||||
|
||||
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.
|
||||
# Use the parent's handling of required fields, etc.
|
||||
super(MultiEmailField, self).validate(value)
|
||||
|
||||
for email in value:
|
||||
validate_email(email)
|
||||
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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
|
||||
===========
|
||||
|
||||
|
|
|
@ -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
|
||||
==============
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue