summaryrefslogtreecommitdiff
path: root/docs/topics/forms
diff options
context:
space:
mode:
Diffstat (limited to 'docs/topics/forms')
-rw-r--r--docs/topics/forms/modelforms.txt163
1 files changed, 83 insertions, 80 deletions
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt
index eaf2bbbaf2..e58dade736 100644
--- a/docs/topics/forms/modelforms.txt
+++ b/docs/topics/forms/modelforms.txt
@@ -28,6 +28,7 @@ For example::
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
+ ... fields = ['pub_date', 'headline', 'content', 'reporter']
# Creating a form to add an article.
>>> form = ArticleForm()
@@ -39,11 +40,13 @@ For example::
Field types
-----------
-The generated ``Form`` class will have a form field for every model field. Each
-model field has a corresponding default form field. For example, a
-``CharField`` on a model is represented as a ``CharField`` on a form. A
-model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
-the full list of conversions:
+The generated ``Form`` class will have a form field for every model field
+specified, in the order specified in the ``fields`` attribute.
+
+Each model field has a corresponding default form field. For example, a
+``CharField`` on a model is represented as a ``CharField`` on a form. A model
+``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is the
+full list of conversions:
=============================== ========================================
Model field Form field
@@ -168,10 +171,13 @@ Consider this set of models::
class AuthorForm(ModelForm):
class Meta:
model = Author
+ fields = ['name', 'title', 'birth_date']
class BookForm(ModelForm):
class Meta:
model = Book
+ fields = ['name', 'authors']
+
With these models, the ``ModelForm`` subclasses above would be roughly
equivalent to this (the only difference being the ``save()`` method, which
@@ -288,47 +294,66 @@ method is used to determine whether a form requires multipart file upload (and
hence whether ``request.FILES`` must be passed to the form), etc. See
:ref:`binding-uploaded-files` for more information.
-Using a subset of fields on the form
-------------------------------------
+.. _modelforms-selecting-fields:
-In some cases, you may not want all the model fields to appear on the generated
-form. There are three ways of telling ``ModelForm`` to use only a subset of the
-model fields:
+Selecting the fields to use
+---------------------------
-1. Set ``editable=False`` on the model field. As a result, *any* form
- created from the model via ``ModelForm`` will not include that
- field.
+It is strongly recommended that you explicitly set all fields that should be
+edited in the form using the ``fields`` attribute. Failure to do so can easily
+lead to security problems when a form unexpectedly allows a user to set certain
+fields, especially when new fields are added to a model. Depending on how the
+form is rendered, the problem may not even be visible on the web page.
-2. Use the ``fields`` attribute of the ``ModelForm``'s inner ``Meta``
- class. This attribute, if given, should be a list of field names
- to include in the form. The order in which the fields names are specified
- in that list is respected when the form renders them.
+The alternative approach would be to include all fields automatically, or
+blacklist only some. This fundamental approach is known to be much less secure
+and has led to serious exploits on major websites (e.g. `GitHub
+<https://github.com/blog/1068-public-key-security-vulnerability-and-mitigation>`_).
-3. Use the ``exclude`` attribute of the ``ModelForm``'s inner ``Meta``
- class. This attribute, if given, should be a list of field names
- to exclude from the form.
+There are, however, two shortcuts available for cases where you can guarantee
+these security concerns do not apply to you:
-For example, if you want a form for the ``Author`` model (defined
-above) that includes only the ``name`` and ``birth_date`` fields, you would
-specify ``fields`` or ``exclude`` like this::
+1. Set the ``fields`` attribute to the special value ``'__all__'`` to indicate
+ that all fields in the model should be used. For example::
- class PartialAuthorForm(ModelForm):
- class Meta:
- model = Author
- fields = ('name', 'birth_date')
+ class AuthorForm(ModelForm):
+ class Meta:
+ model = Author
+ fields = '__all__'
- class PartialAuthorForm(ModelForm):
- class Meta:
- model = Author
- exclude = ('title',)
+2. Set the ``exclude`` attribute of the ``ModelForm``'s inner ``Meta`` class to
+ a list of fields to be excluded from the form.
+
+ For example::
+
+ class PartialAuthorForm(ModelForm):
+ class Meta:
+ model = Author
+ exclude = ['title']
+
+ Since the ``Author`` model has the 3 fields ``name``, ``title`` and
+ ``birth_date``, this will result in the fields ``name`` and ``birth_date``
+ being present on the form.
+
+If either of these are used, the order the fields appear in the form will be the
+order the fields are defined in the model, with ``ManyToManyField`` instances
+appearing last.
+
+In addition, Django applies the following rule: if you set ``editable=False`` on
+the model field, *any* form created from the model via ``ModelForm`` will not
+include that field.
+
+.. versionchanged:: 1.6
+
+ Before version 1.6, the ``'__all__'`` shortcut did not exist, but omitting
+ the ``fields`` attribute had the same effect. Omitting both ``fields`` and
+ ``exclude`` is now deprecated, but will continue to work as before until
+ version 1.8
-Since the Author model has only 3 fields, 'name', 'title', and
-'birth_date', the forms above will contain exactly the same fields.
.. note::
- If you specify ``fields`` or ``exclude`` when creating a form with
- ``ModelForm``, then the fields that are not in the resulting form
+ Any fields not included in a form by the above logic
will not be set by the form's ``save()`` method. Also, if you
manually add the excluded fields back to the form, they will not
be initialized from the model instance.
@@ -401,15 +426,19 @@ field, you could do the following::
class Meta:
model = Article
+ fields = ['pub_date', 'headline', 'content', 'reporter']
+
If you want to override a field's default label, then specify the ``label``
parameter when declaring the form field::
- >>> class ArticleForm(ModelForm):
- ... pub_date = DateField(label='Publication date')
- ...
- ... class Meta:
- ... model = Article
+ class ArticleForm(ModelForm):
+ pub_date = DateField(label='Publication date')
+
+ class Meta:
+ model = Article
+ fields = ['pub_date', 'headline', 'content', 'reporter']
+
.. note::
@@ -436,6 +465,7 @@ parameter when declaring the form field::
class Meta:
model = Article
+ fields = ['headline', 'content']
You must ensure that the type of the form field can be used to set the
contents of the corresponding model field. When they are not compatible,
@@ -444,30 +474,6 @@ parameter when declaring the form field::
See the :doc:`form field documentation </ref/forms/fields>` for more information
on fields and their arguments.
-Changing the order of fields
-----------------------------
-
-By default, a ``ModelForm`` will render fields in the same order that they are
-defined on the model, with ``ManyToManyField`` instances appearing last. If
-you want to change the order in which fields are rendered, you can use the
-``fields`` attribute on the ``Meta`` class.
-
-The ``fields`` attribute defines the subset of model fields that will be
-rendered, and the order in which they will be rendered. For example given this
-model::
-
- class Book(models.Model):
- author = models.ForeignKey(Author)
- title = models.CharField(max_length=100)
-
-the ``author`` field would be rendered first. If we wanted the title field
-to be rendered first, we could specify the following ``ModelForm``::
-
- >>> class BookForm(ModelForm):
- ... class Meta:
- ... model = Book
- ... fields = ('title', 'author')
-
.. _overriding-modelform-clean-method:
Overriding the clean() method
@@ -550,21 +556,19 @@ definition. This may be more convenient if you do not have many customizations
to make::
>>> from django.forms.models import modelform_factory
- >>> BookForm = modelform_factory(Book)
+ >>> BookForm = modelform_factory(Book, fields=("author", "title"))
This can also be used to make simple modifications to existing forms, for
-example by specifying which fields should be displayed::
-
- >>> Form = modelform_factory(Book, form=BookForm, fields=("author",))
-
-... or which fields should be excluded::
-
- >>> Form = modelform_factory(Book, form=BookForm, exclude=("title",))
-
-You can also specify the widgets to be used for a given field::
+example by specifying the widgets to be used for a given field::
>>> from django.forms import Textarea
- >>> Form = modelform_factory(Book, form=BookForm, widgets={"title": Textarea()})
+ >>> Form = modelform_factory(Book, form=BookForm,
+ widgets={"title": Textarea()})
+
+The fields to include can be specified using the ``fields`` and ``exclude``
+keyword arguments, or the corresponding attributes on the ``ModelForm`` inner
+``Meta`` class. Please see the ``ModelForm`` :ref:`modelforms-selecting-fields`
+documentation.
.. _model-formsets:
@@ -688,11 +692,10 @@ database. If a given instance's data didn't change in the bound data, the
instance won't be saved to the database and won't be included in the return
value (``instances``, in the above example).
-When fields are missing from the form (for example because they have
-been excluded), these fields will not be set by the ``save()``
-method. You can find more information about this restriction, which
-also holds for regular ``ModelForms``, in `Using a subset of fields on
-the form`_.
+When fields are missing from the form (for example because they have been
+excluded), these fields will not be set by the ``save()`` method. You can find
+more information about this restriction, which also holds for regular
+``ModelForms``, in `Selecting the fields to use`_.
Pass ``commit=False`` to return the unsaved model instances::