Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Reworked docs for ModelForm validation.

  • Loading branch information...
commit fba6c2ede7b25ed8c71a18dede00865dbc5b85af 1 parent ce5c8a3
@loic loic authored timgraham committed
Showing with 83 additions and 52 deletions.
  1. +83 −52 docs/topics/forms/modelforms.txt
View
135 docs/topics/forms/modelforms.txt
@@ -197,29 +197,89 @@ we'll discuss in a moment.)::
name = forms.CharField(max_length=100)
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
-.. _modelform-is-valid-and-errors:
+.. _validation-on-modelform:
-The ``is_valid()`` method and ``errors``
-----------------------------------------
+Validation on a ``ModelForm``
+-----------------------------
+
+There are two main steps involved in validating a ``ModelForm``:
+
+1. :ref:`Validating the form <form-and-field-validation>`
+2. :ref:`Validating the model instance <validating-objects>`
+
+Just like normal form validation, model form validation is triggered implicitly
+when calling :meth:`~django.forms.Form.is_valid()` or accessing the
+:attr:`~django.forms.Form.errors` attribute and explicitly when calling
+``full_clean()``, although you will typically not use the latter method in
+practice.
+
+``Model`` validation (:meth:`Model.full_clean()
+<django.db.models.Model.full_clean()>`) is triggered from within the form
+validation step, right after the form's ``clean()`` method is called.
+
+.. warning::
-The first time you call ``is_valid()`` or access the ``errors`` attribute of a
-``ModelForm`` triggers :ref:`form validation <form-and-field-validation>` as
-well as :ref:`model validation <validating-objects>`. This has the side-effect
-of cleaning the model you pass to the ``ModelForm`` constructor. For instance,
-calling ``is_valid()`` on your form will convert any date fields on your model
-to actual date objects. If form validation fails, only some of the updates
-may be applied. For this reason, you'll probably want to avoid reusing the
-model instance passed to the form, especially if validation fails.
+ The cleaning process modifies the model instance passed to the
+ ``ModelForm`` constructor in various ways. For instance, any date fields on
+ the model are converted into actual date objects. Failed validation may
+ leave the underlying model instance in an inconsistent state and therefore
+ it's not recommended to reuse it.
+.. _overriding-modelform-clean-method:
+
+Overriding the clean() method
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can override the ``clean()`` method on a model form to provide additional
+validation in the same way you can on a normal form.
+
+A model form instance bound to a model object will contain an ``instance``
+attribute that gives its methods access to that specific model instance.
+
+.. warning::
+
+ The ``ModelForm.clean()`` method sets a flag that makes the :ref:`model
+ validation <validating-objects>` step validate the uniqueness of model
+ fields that are marked as ``unique``, ``unique_together`` or
+ ``unique_for_date|month|year``.
+
+ If you would like to override the ``clean()`` method and maintain this
+ validation, you must call the parent class's ``clean()`` method.
+
+Interaction with model validation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As part of the validation process, ``ModelForm`` will call the ``clean()``
+method of each field on your model that has a corresponding field on your form.
+If you have excluded any model fields, validation will not be run on those
+fields. See the :doc:`form validation </ref/forms/validation>` documentation
+for more on how field cleaning and validation work.
+
+The model's ``clean()`` method will be called before any uniqueness checks are
+made. See :ref:`Validating objects <validating-objects>` for more information
+on the model's ``clean()`` hook.
+
+Considerations regarding fields' ``error_messages``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Error messages defined at the
+:attr:`form field <django.forms.Field.error_messages>` level or at the
+:ref:`form Meta <modelforms-overriding-default-fields>` level always take
+precedence over the error messages defined at the
+:attr:`model field <django.db.models.Field.error_messages>` level.
+Error messages defined on :attr:`model fields
+<django.db.models.Field.error_messages>` are only used when the
+``ValidationError`` is raised during the :ref:`model validation
+<validating-objects>` step and no corresponding error messages are defined at
+the form level.
The ``save()`` method
---------------------
-Every form produced by ``ModelForm`` also has a ``save()``
-method. This method creates and saves a database object from the data
-bound to the form. A subclass of ``ModelForm`` can accept an existing
-model instance as the keyword argument ``instance``; if this is
-supplied, ``save()`` will update that instance. If it's not supplied,
+Every ``ModelForm`` also has a ``save()`` method. This method creates and saves
+a database object from the data bound to the form. A subclass of ``ModelForm``
+can accept an existing model instance as the keyword argument ``instance``; if
+this is supplied, ``save()`` will update that instance. If it's not supplied,
``save()`` will create a new instance of the specified model:
.. code-block:: python
@@ -240,7 +300,7 @@ supplied, ``save()`` will update that instance. If it's not supplied,
>>> f.save()
Note that if the form :ref:`hasn't been validated
-<modelform-is-valid-and-errors>`, calling ``save()`` will do so by checking
+<validation-on-modelform>`, calling ``save()`` will do so by checking
``form.errors``. A ``ValueError`` will be raised if the data in the form
doesn't validate -- i.e., if ``form.errors`` evaluates to ``True``.
@@ -263,7 +323,9 @@ exists in the database.
To work around this problem, every time you save a form using ``commit=False``,
Django adds a ``save_m2m()`` method to your ``ModelForm`` subclass. After
you've manually saved the instance produced by the form, you can invoke
-``save_m2m()`` to save the many-to-many form data. For example::
+``save_m2m()`` to save the many-to-many form data. For example:
+
+.. code-block:: python
# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)
@@ -283,7 +345,9 @@ you've manually saved the instance produced by the form, you can invoke
Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
When you use a simple ``save()`` on a form, all data -- including
many-to-many data -- is saved without the need for any additional method calls.
-For example::
+For example:
+
+.. code-block:: python
# Create a form instance with POST data.
>>> a = Author()
@@ -537,27 +601,6 @@ attribute on the ``Meta`` class.
If ``localized_fields`` is set to the special value ``'__all__'``, all fields
will be localized.
-.. _overriding-modelform-clean-method:
-
-Overriding the clean() method
------------------------------
-
-You can override the ``clean()`` method on a model form to provide additional
-validation in the same way you can on a normal form.
-
-In this regard, model forms have two specific characteristics when compared to
-forms:
-
-By default the ``clean()`` method validates the uniqueness of fields that are
-marked as ``unique``, ``unique_together`` or ``unique_for_date|month|year`` on
-the model. Therefore, if you would like to override the ``clean()`` method and
-maintain the default validation, you must call the parent class's ``clean()``
-method.
-
-Also, a model form instance bound to a model object will contain a
-``self.instance`` attribute that gives model form methods access to that
-specific model instance.
-
Form inheritance
----------------
@@ -596,18 +639,6 @@ There are a couple of things to note, however.
Chances are these notes won't affect you unless you're trying to do something
tricky with subclassing.
-Interaction with model validation
----------------------------------
-
-As part of its validation process, ``ModelForm`` will call the ``clean()``
-method of each field on your model that has a corresponding field on your form.
-If you have excluded any model fields, validation will not be run on those
-fields. See the :doc:`form validation </ref/forms/validation>` documentation
-for more on how field cleaning and validation work. Also, your model's
-``clean()`` method will be called before any uniqueness checks are made. See
-:ref:`Validating objects <validating-objects>` for more information on the
-model's ``clean()`` hook.
-
.. _modelforms-factory:
ModelForm factory function
Please sign in to comment.
Something went wrong with that request. Please try again.