mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1022 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1022 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ==========================
 | |
| Creating forms from models
 | |
| ==========================
 | |
| 
 | |
| .. module:: django.forms.models
 | |
|    :synopsis: ModelForm and ModelFormset.
 | |
| 
 | |
| .. currentmodule:: django.forms
 | |
| 
 | |
| ``ModelForm``
 | |
| =============
 | |
| .. class:: ModelForm
 | |
| 
 | |
| If you're building a database-driven app, chances are you'll have forms that
 | |
| map closely to Django models. For instance, you might have a ``BlogComment``
 | |
| model, and you want to create a form that lets people submit comments. In this
 | |
| case, it would be redundant to define the field types in your form, because
 | |
| you've already defined the fields in your model.
 | |
| 
 | |
| For this reason, Django provides a helper class that let you create a ``Form``
 | |
| class from a Django model.
 | |
| 
 | |
| For example::
 | |
| 
 | |
|     >>> from django.forms import ModelForm
 | |
|     >>> from myapp.models import Article
 | |
| 
 | |
|     # Create the form class.
 | |
|     >>> class ArticleForm(ModelForm):
 | |
|     ...     class Meta:
 | |
|     ...         model = Article
 | |
|     ...         fields = ['pub_date', 'headline', 'content', 'reporter']
 | |
| 
 | |
|     # Creating a form to add an article.
 | |
|     >>> form = ArticleForm()
 | |
| 
 | |
|     # Creating a form to change an existing article.
 | |
|     >>> article = Article.objects.get(pk=1)
 | |
|     >>> form = ArticleForm(instance=article)
 | |
| 
 | |
| Field types
 | |
| -----------
 | |
| 
 | |
| 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
 | |
| ===============================  ========================================
 | |
| ``AutoField``                    Not represented in the form
 | |
| 
 | |
| ``BigIntegerField``              ``IntegerField`` with ``min_value`` set
 | |
|                                  to -9223372036854775808 and ``max_value``
 | |
|                                  set to 9223372036854775807.
 | |
| 
 | |
| ``BooleanField``                 ``BooleanField``
 | |
| 
 | |
| ``CharField``                    ``CharField`` with ``max_length`` set to
 | |
|                                  the model field's ``max_length``
 | |
| 
 | |
| ``CommaSeparatedIntegerField``   ``CharField``
 | |
| 
 | |
| ``DateField``                    ``DateField``
 | |
| 
 | |
| ``DateTimeField``                ``DateTimeField``
 | |
| 
 | |
| ``DecimalField``                 ``DecimalField``
 | |
| 
 | |
| ``EmailField``                   ``EmailField``
 | |
| 
 | |
| ``FileField``                    ``FileField``
 | |
| 
 | |
| ``FilePathField``                ``FilePathField``
 | |
| 
 | |
| ``FloatField``                   ``FloatField``
 | |
| 
 | |
| ``ForeignKey``                   ``ModelChoiceField`` (see below)
 | |
| 
 | |
| ``ImageField``                   ``ImageField``
 | |
| 
 | |
| ``IntegerField``                 ``IntegerField``
 | |
| 
 | |
| ``IPAddressField``               ``IPAddressField``
 | |
| 
 | |
| ``GenericIPAddressField``        ``GenericIPAddressField``
 | |
| 
 | |
| ``ManyToManyField``              ``ModelMultipleChoiceField`` (see
 | |
|                                  below)
 | |
| 
 | |
| ``NullBooleanField``             ``CharField``
 | |
| 
 | |
| ``PositiveIntegerField``         ``IntegerField``
 | |
| 
 | |
| ``PositiveSmallIntegerField``    ``IntegerField``
 | |
| 
 | |
| ``SlugField``                    ``SlugField``
 | |
| 
 | |
| ``SmallIntegerField``            ``IntegerField``
 | |
| 
 | |
| ``TextField``                    ``CharField`` with
 | |
|                                  ``widget=forms.Textarea``
 | |
| 
 | |
| ``TimeField``                    ``TimeField``
 | |
| 
 | |
| ``URLField``                     ``URLField``
 | |
| ===============================  ========================================
 | |
| 
 | |
| 
 | |
| As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
 | |
| types are special cases:
 | |
| 
 | |
| * ``ForeignKey`` is represented by ``django.forms.ModelChoiceField``,
 | |
|   which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
 | |
| 
 | |
| * ``ManyToManyField`` is represented by
 | |
|   ``django.forms.ModelMultipleChoiceField``, which is a
 | |
|   ``MultipleChoiceField`` whose choices are a model ``QuerySet``.
 | |
| 
 | |
| In addition, each generated form field has attributes set as follows:
 | |
| 
 | |
| * If the model field has ``blank=True``, then ``required`` is set to
 | |
|   ``False`` on the form field. Otherwise, ``required=True``.
 | |
| 
 | |
| * The form field's ``label`` is set to the ``verbose_name`` of the model
 | |
|   field, with the first character capitalized.
 | |
| 
 | |
| * The form field's ``help_text`` is set to the ``help_text`` of the model
 | |
|   field.
 | |
| 
 | |
| * If the model field has ``choices`` set, then the form field's ``widget``
 | |
|   will be set to ``Select``, with choices coming from the model field's
 | |
|   ``choices``. The choices will normally include the blank choice which is
 | |
|   selected by default. If the field is required, this forces the user to
 | |
|   make a selection. The blank choice will not be included if the model
 | |
|   field has ``blank=False`` and an explicit ``default`` value (the
 | |
|   ``default`` value will be initially selected instead).
 | |
| 
 | |
| Finally, note that you can override the form field used for a given model
 | |
| field. See `Overriding the default field types or widgets`_ below.
 | |
| 
 | |
| A full example
 | |
| --------------
 | |
| 
 | |
| Consider this set of models::
 | |
| 
 | |
|     from django.db import models
 | |
|     from django.forms import ModelForm
 | |
| 
 | |
|     TITLE_CHOICES = (
 | |
|         ('MR', 'Mr.'),
 | |
|         ('MRS', 'Mrs.'),
 | |
|         ('MS', 'Ms.'),
 | |
|     )
 | |
| 
 | |
|     class Author(models.Model):
 | |
|         name = models.CharField(max_length=100)
 | |
|         title = models.CharField(max_length=3, choices=TITLE_CHOICES)
 | |
|         birth_date = models.DateField(blank=True, null=True)
 | |
| 
 | |
|         def __unicode__(self):
 | |
|             return self.name
 | |
| 
 | |
|     class Book(models.Model):
 | |
|         name = models.CharField(max_length=100)
 | |
|         authors = models.ManyToManyField(Author)
 | |
| 
 | |
|     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
 | |
| we'll discuss in a moment.)::
 | |
| 
 | |
|     from django import forms
 | |
| 
 | |
|     class AuthorForm(forms.Form):
 | |
|         name = forms.CharField(max_length=100)
 | |
|         title = forms.CharField(max_length=3,
 | |
|                     widget=forms.Select(choices=TITLE_CHOICES))
 | |
|         birth_date = forms.DateField(required=False)
 | |
| 
 | |
|     class BookForm(forms.Form):
 | |
|         name = forms.CharField(max_length=100)
 | |
|         authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
 | |
| 
 | |
| .. _modelform-is-valid-and-errors:
 | |
| 
 | |
| The ``is_valid()`` method and ``errors``
 | |
| ----------------------------------------
 | |
| 
 | |
| 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 ``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,
 | |
| ``save()`` will create a new instance of the specified model:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     >>> from myapp.models import Article
 | |
|     >>> from myapp.forms import ArticleForm
 | |
| 
 | |
|     # Create a form instance from POST data.
 | |
|     >>> f = ArticleForm(request.POST)
 | |
| 
 | |
|     # Save a new Article object from the form's data.
 | |
|     >>> new_article = f.save()
 | |
| 
 | |
|     # Create a form to edit an existing Article, but use
 | |
|     # POST data to populate the form.
 | |
|     >>> a = Article.objects.get(pk=1)
 | |
|     >>> f = ArticleForm(request.POST, instance=a)
 | |
|     >>> f.save()
 | |
| 
 | |
| Note that if the form :ref:`hasn't been validated
 | |
| <modelform-is-valid-and-errors>`, 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``.
 | |
| 
 | |
| This ``save()`` method accepts an optional ``commit`` keyword argument, which
 | |
| accepts either ``True`` or ``False``. If you call ``save()`` with
 | |
| ``commit=False``, then it will return an object that hasn't yet been saved to
 | |
| the database. In this case, it's up to you to call ``save()`` on the resulting
 | |
| model instance. This is useful if you want to do custom processing on the
 | |
| object before saving it, or if you want to use one of the specialized
 | |
| :ref:`model saving options <ref-models-force-insert>`. ``commit`` is ``True``
 | |
| by default.
 | |
| 
 | |
| Another side effect of using ``commit=False`` is seen when your model has
 | |
| a many-to-many relation with another model. If your model has a many-to-many
 | |
| relation and you specify ``commit=False`` when you save a form, Django cannot
 | |
| immediately save the form data for the many-to-many relation. This is because
 | |
| it isn't possible to save many-to-many data for an instance until the instance
 | |
| 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::
 | |
| 
 | |
|     # Create a form instance with POST data.
 | |
|     >>> f = AuthorForm(request.POST)
 | |
| 
 | |
|     # Create, but don't save the new author instance.
 | |
|     >>> new_author = f.save(commit=False)
 | |
| 
 | |
|     # Modify the author in some way.
 | |
|     >>> new_author.some_field = 'some_value'
 | |
| 
 | |
|     # Save the new instance.
 | |
|     >>> new_author.save()
 | |
| 
 | |
|     # Now, save the many-to-many data for the form.
 | |
|     >>> f.save_m2m()
 | |
| 
 | |
| 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::
 | |
| 
 | |
|     # Create a form instance with POST data.
 | |
|     >>> a = Author()
 | |
|     >>> f = AuthorForm(request.POST, instance=a)
 | |
| 
 | |
|     # Create and save the new author instance. There's no need to do anything else.
 | |
|     >>> new_author = f.save()
 | |
| 
 | |
| Other than the ``save()`` and ``save_m2m()`` methods, a ``ModelForm`` works
 | |
| exactly the same way as any other ``forms`` form. For example, the
 | |
| ``is_valid()`` method is used to check for validity, the ``is_multipart()``
 | |
| 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.
 | |
| 
 | |
| .. _modelforms-selecting-fields:
 | |
| 
 | |
| Selecting the fields to use
 | |
| ---------------------------
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 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>`_).
 | |
| 
 | |
| There are, however, two shortcuts available for cases where you can guarantee
 | |
| these security concerns do not apply to you:
 | |
| 
 | |
| 1. Set the ``fields`` attribute to the special value ``'__all__'`` to indicate
 | |
|    that all fields in the model should be used. For example::
 | |
| 
 | |
|        from django.forms import ModelForm
 | |
| 
 | |
|        class AuthorForm(ModelForm):
 | |
|            class Meta:
 | |
|                model = Author
 | |
|                fields = '__all__'
 | |
| 
 | |
| 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
 | |
| 
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     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.
 | |
| 
 | |
|     Django will prevent any attempt to save an incomplete model, so if
 | |
|     the model does not allow the missing fields to be empty, and does
 | |
|     not provide a default value for the missing fields, any attempt to
 | |
|     ``save()`` a ``ModelForm`` with missing fields will fail.  To
 | |
|     avoid this failure, you must instantiate your model with initial
 | |
|     values for the missing, but required fields::
 | |
| 
 | |
|         author = Author(title='Mr')
 | |
|         form = PartialAuthorForm(request.POST, instance=author)
 | |
|         form.save()
 | |
| 
 | |
|     Alternatively, you can use ``save(commit=False)`` and manually set
 | |
|     any extra required fields::
 | |
| 
 | |
|         form = PartialAuthorForm(request.POST)
 | |
|         author = form.save(commit=False)
 | |
|         author.title = 'Mr'
 | |
|         author.save()
 | |
| 
 | |
|     See the `section on saving forms`_ for more details on using
 | |
|     ``save(commit=False)``.
 | |
| 
 | |
| .. _section on saving forms: `The save() method`_
 | |
| 
 | |
| Overriding the default field types or widgets
 | |
| ---------------------------------------------
 | |
| 
 | |
| The default field types, as described in the `Field types`_ table above, are
 | |
| sensible defaults. If you have a ``DateField`` in your model, chances are you'd
 | |
| want that to be represented as a ``DateField`` in your form. But
 | |
| ``ModelForm`` gives you the flexibility of changing the form field type and
 | |
| widget for a given model field.
 | |
| 
 | |
| To specify a custom widget for a field, use the ``widgets`` attribute of the
 | |
| inner ``Meta`` class. This should be a dictionary mapping field names to widget
 | |
| classes or instances.
 | |
| 
 | |
| For example, if you want the a ``CharField`` for the ``name``
 | |
| attribute of ``Author`` to be represented by a ``<textarea>`` instead
 | |
| of its default ``<input type="text">``, you can override the field's
 | |
| widget::
 | |
| 
 | |
|     from django.forms import ModelForm, Textarea
 | |
|     from myapp.models import Author
 | |
| 
 | |
|     class AuthorForm(ModelForm):
 | |
|         class Meta:
 | |
|             model = Author
 | |
|             fields = ('name', 'title', 'birth_date')
 | |
|             widgets = {
 | |
|                 'name': Textarea(attrs={'cols': 80, 'rows': 20}),
 | |
|             }
 | |
| 
 | |
| The ``widgets`` dictionary accepts either widget instances (e.g.,
 | |
| ``Textarea(...)``) or classes (e.g., ``Textarea``).
 | |
| 
 | |
| If you want to further customize a field -- including its type, label, etc. --
 | |
| you can do this by declaratively specifying fields like you would in a regular
 | |
| ``Form``. Declared fields will override the default ones generated by using the
 | |
| ``model`` attribute.
 | |
| 
 | |
| For example, if you wanted to use ``MyDateFormField`` for the ``pub_date``
 | |
| field, you could do the following::
 | |
| 
 | |
|     from django.forms import ModelForm
 | |
|     from myapp.models import Article
 | |
| 
 | |
|     class ArticleForm(ModelForm):
 | |
|         pub_date = MyDateFormField()
 | |
| 
 | |
|         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::
 | |
| 
 | |
|     from django.forms import ModelForm, DateField
 | |
|     from myapp.models import Article
 | |
| 
 | |
|     class ArticleForm(ModelForm):
 | |
|         pub_date = DateField(label='Publication date')
 | |
| 
 | |
|         class Meta:
 | |
|             model = Article
 | |
|             fields = ['pub_date', 'headline', 'content', 'reporter']
 | |
| 
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     If you explicitly instantiate a form field like this, Django assumes that you
 | |
|     want to completely define its behavior; therefore, default attributes (such as
 | |
|     ``max_length`` or ``required``) are not drawn from the corresponding model. If
 | |
|     you want to maintain the behavior specified in the model, you must set the
 | |
|     relevant arguments explicitly when declaring the form field.
 | |
| 
 | |
|     For example, if the ``Article`` model looks like this::
 | |
| 
 | |
|         class Article(models.Model):
 | |
|             headline = models.CharField(max_length=200, null=True, blank=True,
 | |
|                                         help_text="Use puns liberally")
 | |
|             content = models.TextField()
 | |
| 
 | |
|     and you want to do some custom validation for ``headline``, while keeping
 | |
|     the ``blank`` and ``help_text`` values as specified, you might define
 | |
|     ``ArticleForm`` like this::
 | |
| 
 | |
|         class ArticleForm(ModelForm):
 | |
|             headline = MyFormField(max_length=200, required=False,
 | |
|                                    help_text="Use puns liberally")
 | |
| 
 | |
|             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,
 | |
|     you will get a ``ValueError`` as no implicit conversion takes place.
 | |
| 
 | |
|     See the :doc:`form field documentation </ref/forms/fields>` for more information
 | |
|     on fields and their arguments.
 | |
| 
 | |
| 
 | |
| Enabling localization of fields
 | |
| -------------------------------
 | |
| 
 | |
| .. versionadded:: 1.6
 | |
| 
 | |
| By default, the fields in a ``ModelForm`` will not localize their data. To
 | |
| enable localization for fields, you can use the ``localized_fields``
 | |
| attribute on the ``Meta`` class.
 | |
| 
 | |
|     >>> from django.forms import ModelForm
 | |
|     >>> from myapp.models import Author
 | |
|     >>> class AuthorForm(ModelForm):
 | |
|     ...     class Meta:
 | |
|     ...         model = Author
 | |
|     ...         localized_fields = ('birth_date',)
 | |
| 
 | |
| 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
 | |
| ----------------
 | |
| 
 | |
| As with basic forms, you can extend and reuse ``ModelForms`` by inheriting
 | |
| them. This is useful if you need to declare extra fields or extra methods on a
 | |
| parent class for use in a number of forms derived from models. For example,
 | |
| using the previous ``ArticleForm`` class::
 | |
| 
 | |
|     >>> class EnhancedArticleForm(ArticleForm):
 | |
|     ...     def clean_pub_date(self):
 | |
|     ...         ...
 | |
| 
 | |
| This creates a form that behaves identically to ``ArticleForm``, except there's
 | |
| some extra validation and cleaning for the ``pub_date`` field.
 | |
| 
 | |
| You can also subclass the parent's ``Meta`` inner class if you want to change
 | |
| the ``Meta.fields`` or ``Meta.excludes`` lists::
 | |
| 
 | |
|     >>> class RestrictedArticleForm(EnhancedArticleForm):
 | |
|     ...     class Meta(ArticleForm.Meta):
 | |
|     ...         exclude = ('body',)
 | |
| 
 | |
| This adds the extra method from the ``EnhancedArticleForm`` and modifies
 | |
| the original ``ArticleForm.Meta`` to remove one field.
 | |
| 
 | |
| There are a couple of things to note, however.
 | |
| 
 | |
| * Normal Python name resolution rules apply. If you have multiple base
 | |
|   classes that declare a ``Meta`` inner class, only the first one will be
 | |
|   used. This means the child's ``Meta``, if it exists, otherwise the
 | |
|   ``Meta`` of the first parent, etc.
 | |
| 
 | |
| * For technical reasons, a subclass cannot inherit from both a ``ModelForm``
 | |
|   and a ``Form`` simultaneously.
 | |
| 
 | |
| 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
 | |
| --------------------------
 | |
| 
 | |
| You can create forms from a given model using the standalone function
 | |
| :func:`~django.forms.models.modelform_factory`, instead of using a class
 | |
| definition. This may be more convenient if you do not have many customizations
 | |
| to make::
 | |
| 
 | |
|     >>> from django.forms.models import modelform_factory
 | |
|     >>> from myapp.models import Book
 | |
|     >>> BookForm = modelform_factory(Book, fields=("author", "title"))
 | |
| 
 | |
| This can also be used to make simple modifications to existing forms, for
 | |
| 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()})
 | |
| 
 | |
| 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.
 | |
| 
 | |
| ... or enable localization for specific fields::
 | |
| 
 | |
|     >>> Form = modelform_factory(Author, form=AuthorForm, localized_fields=("birth_date",))
 | |
| 
 | |
| .. _model-formsets:
 | |
| 
 | |
| Model formsets
 | |
| ==============
 | |
| 
 | |
| .. class:: models.BaseModelFormSet
 | |
| 
 | |
| Like :doc:`regular formsets </topics/forms/formsets>`, Django provides a couple
 | |
| of enhanced formset classes that make it easy to work with Django models. Let's
 | |
| reuse the ``Author`` model from above::
 | |
| 
 | |
|     >>> from django.forms.models import modelformset_factory
 | |
|     >>> from myapp.models import Author
 | |
|     >>> AuthorFormSet = modelformset_factory(Author)
 | |
| 
 | |
| This will create a formset that is capable of working with the data associated
 | |
| with the ``Author`` model. It works just like a regular formset::
 | |
| 
 | |
|     >>> formset = AuthorFormSet()
 | |
|     >>> print(formset)
 | |
|     <input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" />
 | |
|     <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr>
 | |
|     <tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title">
 | |
|     <option value="" selected="selected">---------</option>
 | |
|     <option value="MR">Mr.</option>
 | |
|     <option value="MRS">Mrs.</option>
 | |
|     <option value="MS">Ms.</option>
 | |
|     </select></td></tr>
 | |
|     <tr><th><label for="id_form-0-birth_date">Birth date:</label></th><td><input type="text" name="form-0-birth_date" id="id_form-0-birth_date" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr>
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     :func:`~django.forms.models.modelformset_factory` uses
 | |
|     :func:`~django.forms.formsets.formset_factory` to generate formsets. This
 | |
|     means that a model formset is just an extension of a basic formset that
 | |
|     knows how to interact with a particular model.
 | |
| 
 | |
| Changing the queryset
 | |
| ---------------------
 | |
| 
 | |
| By default, when you create a formset from a model, the formset will use a
 | |
| queryset that includes all objects in the model (e.g.,
 | |
| ``Author.objects.all()``). You can override this behavior by using the
 | |
| ``queryset`` argument::
 | |
| 
 | |
|     >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
 | |
| 
 | |
| Alternatively, you can create a subclass that sets ``self.queryset`` in
 | |
| ``__init__``::
 | |
| 
 | |
|     from django.forms.models import BaseModelFormSet
 | |
|     from myapp.models import Author
 | |
| 
 | |
|     class BaseAuthorFormSet(BaseModelFormSet):
 | |
|         def __init__(self, *args, **kwargs):
 | |
|             super(BaseAuthorFormSet, self).__init__(*args, **kwargs)
 | |
|             self.queryset = Author.objects.filter(name__startswith='O')
 | |
| 
 | |
| Then, pass your ``BaseAuthorFormSet`` class to the factory function::
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(Author, formset=BaseAuthorFormSet)
 | |
| 
 | |
| If you want to return a formset that doesn't include *any* pre-existing
 | |
| instances of the model, you can specify an empty QuerySet::
 | |
| 
 | |
|    >>> AuthorFormSet(queryset=Author.objects.none())
 | |
| 
 | |
| 
 | |
| Controlling which fields are used with ``fields`` and ``exclude``
 | |
| -----------------------------------------------------------------
 | |
| 
 | |
| By default, a model formset uses all fields in the model that are not marked
 | |
| with ``editable=False``. However, this can be overridden at the formset level::
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
 | |
| 
 | |
| Using ``fields`` restricts the formset to use only the given fields.
 | |
| Alternatively, you can take an "opt-out" approach, specifying which fields to
 | |
| exclude::
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))
 | |
| 
 | |
| Specifying widgets to use in the form with ``widgets``
 | |
| ------------------------------------------------------
 | |
| 
 | |
| .. versionadded:: 1.6
 | |
| 
 | |
| Using the ``widgets`` parameter, you can specify a dictionary of values to
 | |
| customize the ``ModelForm``'s widget class for a particular field. This
 | |
| works the same way as the ``widgets`` dictionary on the inner ``Meta``
 | |
| class of a ``ModelForm`` works::
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(
 | |
|     ...     Author, widgets={'name': Textarea(attrs={'cols': 80, 'rows': 20})
 | |
| 
 | |
| Enabling localization for fields with ``localized_fields``
 | |
| ----------------------------------------------------------
 | |
| 
 | |
| .. versionadded:: 1.6
 | |
| 
 | |
| Using the ``localized_fields`` parameter, you can enable localization for
 | |
| fields in the form.
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(
 | |
|     ...     Author, localized_fields=('value',))
 | |
| 
 | |
| If ``localized_fields`` is set to the special value ``'__all__'``, all fields
 | |
| will be localized.
 | |
| 
 | |
| Providing initial values
 | |
| ------------------------
 | |
| 
 | |
| As with regular formsets, it's possible to :ref:`specify initial data
 | |
| <formsets-initial-data>` for forms in the formset by specifying an ``initial``
 | |
| parameter when instantiating the model formset class returned by
 | |
| :func:`~django.forms.models.modelformset_factory`. However, with model
 | |
| formsets, the initial values only apply to extra forms, those that aren't bound
 | |
| to an existing object instance.
 | |
| 
 | |
| .. _saving-objects-in-the-formset:
 | |
| 
 | |
| Saving objects in the formset
 | |
| -----------------------------
 | |
| 
 | |
| As with a ``ModelForm``, you can save the data as a model object. This is done
 | |
| with the formset's ``save()`` method::
 | |
| 
 | |
|     # Create a formset instance with POST data.
 | |
|     >>> formset = AuthorFormSet(request.POST)
 | |
| 
 | |
|     # Assuming all is valid, save the data.
 | |
|     >>> instances = formset.save()
 | |
| 
 | |
| The ``save()`` method returns the instances that have been saved to the
 | |
| 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 `Selecting the fields to use`_.
 | |
| 
 | |
| Pass ``commit=False`` to return the unsaved model instances::
 | |
| 
 | |
|     # don't save to the database
 | |
|     >>> instances = formset.save(commit=False)
 | |
|     >>> for instance in instances:
 | |
|     ...     # do something with instance
 | |
|     ...     instance.save()
 | |
| 
 | |
| This gives you the ability to attach data to the instances before saving them
 | |
| to the database. If your formset contains a ``ManyToManyField``, you'll also
 | |
| need to call ``formset.save_m2m()`` to ensure the many-to-many relationships
 | |
| are saved properly.
 | |
| 
 | |
| .. _model-formsets-max-num:
 | |
| 
 | |
| Limiting the number of editable objects
 | |
| ---------------------------------------
 | |
| 
 | |
| As with regular formsets, you can use the ``max_num`` and ``extra`` parameters
 | |
| to :func:`~django.forms.models.modelformset_factory` to limit the number of
 | |
| extra forms displayed.
 | |
| 
 | |
| ``max_num`` does not prevent existing objects from being displayed::
 | |
| 
 | |
|     >>> Author.objects.order_by('name')
 | |
|     [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(Author, max_num=1)
 | |
|     >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
 | |
|     >>> [x.name for x in formset.get_queryset()]
 | |
|     [u'Charles Baudelaire', u'Paul Verlaine', u'Walt Whitman']
 | |
| 
 | |
| If the value of ``max_num`` is greater than the number of existing related
 | |
| objects, up to ``extra`` additional blank forms will be added to the formset,
 | |
| so long as the total number of forms does not exceed ``max_num``::
 | |
| 
 | |
|     >>> AuthorFormSet = modelformset_factory(Author, max_num=4, extra=2)
 | |
|     >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
 | |
|     >>> for form in formset:
 | |
|     ...     print(form.as_table())
 | |
|     <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr>
 | |
|     <tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr>
 | |
|     <tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr>
 | |
|     <tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr>
 | |
| 
 | |
| A ``max_num`` value of ``None`` (the default) puts a high limit on the number
 | |
| of forms displayed (1000). In practice this is equivalent to no limit.
 | |
| 
 | |
| Using a model formset in a view
 | |
| -------------------------------
 | |
| 
 | |
| Model formsets are very similar to formsets. Let's say we want to present a
 | |
| formset to edit ``Author`` model instances::
 | |
| 
 | |
|     from django.forms.models import modelformset_factory
 | |
|     from django.shortcuts import render_to_response
 | |
|     from myapp.models import Author
 | |
| 
 | |
|     def manage_authors(request):
 | |
|         AuthorFormSet = modelformset_factory(Author)
 | |
|         if request.method == 'POST':
 | |
|             formset = AuthorFormSet(request.POST, request.FILES)
 | |
|             if formset.is_valid():
 | |
|                 formset.save()
 | |
|                 # do something.
 | |
|         else:
 | |
|             formset = AuthorFormSet()
 | |
|         return render_to_response("manage_authors.html", {
 | |
|             "formset": formset,
 | |
|         })
 | |
| 
 | |
| As you can see, the view logic of a model formset isn't drastically different
 | |
| than that of a "normal" formset. The only difference is that we call
 | |
| ``formset.save()`` to save the data into the database. (This was described
 | |
| above, in :ref:`saving-objects-in-the-formset`.)
 | |
| 
 | |
| Overiding ``clean()`` on a ``model_formset``
 | |
| --------------------------------------------
 | |
| 
 | |
| Just like with ``ModelForms``, by default the ``clean()`` method of a
 | |
| ``model_formset`` will validate that none of the items in the formset violate
 | |
| the unique constraints on your model (either ``unique``, ``unique_together`` or
 | |
| ``unique_for_date|month|year``).  If you want to override the ``clean()`` method
 | |
| on a ``model_formset`` and maintain this validation, you must call the parent
 | |
| class's ``clean`` method::
 | |
| 
 | |
|     from django.forms.models import BaseModelFormSet
 | |
| 
 | |
|     class MyModelFormSet(BaseModelFormSet):
 | |
|         def clean(self):
 | |
|             super(MyModelFormSet, self).clean()
 | |
|             # example custom validation across forms in the formset:
 | |
|             for form in self.forms:
 | |
|                 # your custom formset validation
 | |
|                 pass
 | |
| 
 | |
| Using a custom queryset
 | |
| -----------------------
 | |
| 
 | |
| As stated earlier, you can override the default queryset used by the model
 | |
| formset::
 | |
| 
 | |
|     from django.forms.models import modelformset_factory
 | |
|     from django.shortcuts import render_to_response
 | |
|     from myapp.models import Author
 | |
| 
 | |
|     def manage_authors(request):
 | |
|         AuthorFormSet = modelformset_factory(Author)
 | |
|         if request.method == "POST":
 | |
|             formset = AuthorFormSet(request.POST, request.FILES,
 | |
|                                     queryset=Author.objects.filter(name__startswith='O'))
 | |
|             if formset.is_valid():
 | |
|                 formset.save()
 | |
|                 # Do something.
 | |
|         else:
 | |
|             formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
 | |
|         return render_to_response("manage_authors.html", {
 | |
|             "formset": formset,
 | |
|         })
 | |
| 
 | |
| Note that we pass the ``queryset`` argument in both the ``POST`` and ``GET``
 | |
| cases in this example.
 | |
| 
 | |
| Using the formset in the template
 | |
| ---------------------------------
 | |
| 
 | |
| .. highlight:: html+django
 | |
| 
 | |
| There are three ways to render a formset in a Django template.
 | |
| 
 | |
| First, you can let the formset do most of the work::
 | |
| 
 | |
|     <form method="post" action="">
 | |
|         {{ formset }}
 | |
|     </form>
 | |
| 
 | |
| Second, you can manually render the formset, but let the form deal with
 | |
| itself::
 | |
| 
 | |
|     <form method="post" action="">
 | |
|         {{ formset.management_form }}
 | |
|         {% for form in formset %}
 | |
|             {{ form }}
 | |
|         {% endfor %}
 | |
|     </form>
 | |
| 
 | |
| When you manually render the forms yourself, be sure to render the management
 | |
| form as shown above. See the :ref:`management form documentation
 | |
| <understanding-the-managementform>`.
 | |
| 
 | |
| Third, you can manually render each field::
 | |
| 
 | |
|     <form method="post" action="">
 | |
|         {{ formset.management_form }}
 | |
|         {% for form in formset %}
 | |
|             {% for field in form %}
 | |
|                 {{ field.label_tag }}: {{ field }}
 | |
|             {% endfor %}
 | |
|         {% endfor %}
 | |
|     </form>
 | |
| 
 | |
| If you opt to use this third method and you don't iterate over the fields with
 | |
| a ``{% for %}`` loop, you'll need to render the primary key field. For example,
 | |
| if you were rendering the ``name`` and ``age`` fields of a model::
 | |
| 
 | |
|     <form method="post" action="">
 | |
|         {{ formset.management_form }}
 | |
|         {% for form in formset %}
 | |
|             {{ form.id }}
 | |
|             <ul>
 | |
|                 <li>{{ form.name }}</li>
 | |
|                 <li>{{ form.age }}</li>
 | |
|             </ul>
 | |
|         {% endfor %}
 | |
|     </form>
 | |
| 
 | |
| Notice how we need to explicitly render ``{{ form.id }}``. This ensures that
 | |
| the model formset, in the ``POST`` case, will work correctly. (This example
 | |
| assumes a primary key named ``id``. If you've explicitly defined your own
 | |
| primary key that isn't called ``id``, make sure it gets rendered.)
 | |
| 
 | |
| .. highlight:: python
 | |
| 
 | |
| .. _inline-formsets:
 | |
| 
 | |
| Inline formsets
 | |
| ===============
 | |
| 
 | |
| Inline formsets is a small abstraction layer on top of model formsets. These
 | |
| simplify the case of working with related objects via a foreign key. Suppose
 | |
| you have these two models::
 | |
| 
 | |
|     from django.db import models
 | |
| 
 | |
|     class Author(models.Model):
 | |
|         name = models.CharField(max_length=100)
 | |
| 
 | |
|     class Book(models.Model):
 | |
|         author = models.ForeignKey(Author)
 | |
|         title = models.CharField(max_length=100)
 | |
| 
 | |
| If you want to create a formset that allows you to edit books belonging to
 | |
| a particular author, you could do this::
 | |
| 
 | |
|     >>> from django.forms.models import inlineformset_factory
 | |
|     >>> BookFormSet = inlineformset_factory(Author, Book)
 | |
|     >>> author = Author.objects.get(name=u'Mike Royko')
 | |
|     >>> formset = BookFormSet(instance=author)
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     :func:`~django.forms.models.inlineformset_factory` uses
 | |
|     :func:`~django.forms.models.modelformset_factory` and marks
 | |
|     ``can_delete=True``.
 | |
| 
 | |
| .. seealso::
 | |
| 
 | |
|     :ref:`Manually rendered can_delete and can_order <manually-rendered-can-delete-and-can-order>`.
 | |
| 
 | |
| More than one foreign key to the same model
 | |
| -------------------------------------------
 | |
| 
 | |
| If your model contains more than one foreign key to the same model, you'll
 | |
| need to resolve the ambiguity manually using ``fk_name``. For example, consider
 | |
| the following model::
 | |
| 
 | |
|     class Friendship(models.Model):
 | |
|         from_friend = models.ForeignKey(Friend)
 | |
|         to_friend = models.ForeignKey(Friend)
 | |
|         length_in_months = models.IntegerField()
 | |
| 
 | |
| To resolve this, you can use ``fk_name`` to
 | |
| :func:`~django.forms.models.inlineformset_factory`::
 | |
| 
 | |
|     >>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend")
 | |
| 
 | |
| Using an inline formset in a view
 | |
| ---------------------------------
 | |
| 
 | |
| You may want to provide a view that allows a user to edit the related objects
 | |
| of a model. Here's how you can do that::
 | |
| 
 | |
|     def manage_books(request, author_id):
 | |
|         author = Author.objects.get(pk=author_id)
 | |
|         BookInlineFormSet = inlineformset_factory(Author, Book)
 | |
|         if request.method == "POST":
 | |
|             formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
 | |
|             if formset.is_valid():
 | |
|                 formset.save()
 | |
|                 # Do something. Should generally end with a redirect. For example:
 | |
|                 return HttpResponseRedirect(author.get_absolute_url())
 | |
|         else:
 | |
|             formset = BookInlineFormSet(instance=author)
 | |
|         return render_to_response("manage_books.html", {
 | |
|             "formset": formset,
 | |
|         })
 | |
| 
 | |
| Notice how we pass ``instance`` in both the ``POST`` and ``GET`` cases.
 | |
| 
 | |
| Specifying widgets to use in the inline form
 | |
| --------------------------------------------
 | |
| 
 | |
| .. versionadded:: 1.6
 | |
| 
 | |
| ``inlineformset_factory`` uses ``modelformset_factory`` and passes most
 | |
| of its arguments to ``modelformset_factory``. This means you can use
 | |
| the ``widgets`` parameter in much the same way as passing it to
 | |
| ``modelformset_factory``. See `Specifying widgets to use in the form with widgets`_ above.
 |