summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/forms/fields.txt11
-rw-r--r--docs/ref/forms/validation.txt111
-rw-r--r--docs/ref/models/fields.txt22
-rw-r--r--docs/ref/models/instances.txt25
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
==============