--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/parts/django/docs/topics/forms/modelforms.txt Sat Jan 08 11:20:57 2011 +0530
@@ -0,0 +1,885 @@
+==========================
+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
+
+ # Create the form class.
+ >>> class ArticleForm(ModelForm):
+ ... class Meta:
+ ... model = Article
+
+ # 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. 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`` ``CharField``
+
+ ``FloatField`` ``FloatField``
+
+ ``ForeignKey`` ``ModelChoiceField`` (see below)
+
+ ``ImageField`` ``ImageField``
+
+ ``IntegerField`` ``IntegerField``
+
+ ``IPAddressField`` ``IPAddressField``
+
+ ``ManyToManyField`` ``ModelMultipleChoiceField`` (see
+ below)
+
+ ``NullBooleanField`` ``CharField``
+
+ ``PhoneNumberField`` ``USPhoneNumberField``
+ (from ``django.contrib.localflavor.us``)
+
+ ``PositiveIntegerField`` ``IntegerField``
+
+ ``PositiveSmallIntegerField`` ``IntegerField``
+
+ ``SlugField`` ``SlugField``
+
+ ``SmallIntegerField`` ``IntegerField``
+
+ ``TextField`` ``CharField`` with
+ ``widget=forms.Textarea``
+
+ ``TimeField`` ``TimeField``
+
+ ``URLField`` ``URLField`` with ``verify_exists`` set
+ to the model field's ``verify_exists``
+
+ ``XMLField`` ``CharField`` with
+ ``widget=forms.Textarea``
+ =============================== ========================================
+
+
+.. versionadded:: 1.0
+ The ``FloatField`` form field and ``DecimalField`` model and form fields
+ are new in Django 1.0.
+
+.. versionadded:: 1.2
+ The ``BigIntegerField`` is new in Django 1.2.
+
+
+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
+
+ class BookForm(ModelForm):
+ class Meta:
+ model = Book
+
+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.)::
+
+ 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())
+
+The ``is_valid()`` method and ``errors``
+----------------------------------------
+
+.. versionchanged:: 1.2
+
+The first time you call ``is_valid()`` or access the ``errors`` attribute of a
+``ModelForm`` has always triggered form validation, but as of Django 1.2, it
+will also trigger :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.
+
+
+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::
+
+ # 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.
+ >>> a = Article.objects.get(pk=1)
+ >>> f = ArticleForm(instance=a)
+ >>> 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 ``save()`` will raise a ``ValueError`` 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.
+
+Using a subset of fields on the form
+------------------------------------
+
+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:
+
+1. Set ``editable=False`` on the model field. As a result, *any* form
+ created from the model via ``ModelForm`` will not include that
+ field.
+
+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.
+
+ .. versionchanged:: 1.1
+
+ The form will render the fields in the same order they are specified in the
+ ``fields`` attribute.
+
+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.
+
+For example, if you want a form for the ``Author`` model (defined
+above) that includes only the ``name`` and ``title`` fields, you would
+specify ``fields`` or ``exclude`` like this::
+
+ class PartialAuthorForm(ModelForm):
+ class Meta:
+ model = Author
+ fields = ('name', 'title')
+
+ class PartialAuthorForm(ModelForm):
+ class Meta:
+ model = Author
+ exclude = ('birth_date',)
+
+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 will not
+ be set by the form's ``save()`` method. 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
+---------------------------------------------
+
+.. versionadded:: 1.2
+ The ``widgets`` attribute is new in Django 1.2.
+
+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
+
+ 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::
+
+ class ArticleForm(ModelForm):
+ pub_date = MyDateFormField()
+
+ class Meta:
+ model = Article
+
+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
+
+.. 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
+
+ See the :doc:`form field documentation </ref/forms/fields>` for more information
+ on fields and their arguments.
+
+Changing the order of fields
+----------------------------
+
+.. versionadded:: 1.1
+
+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
+-----------------------------
+
+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.
+
+.. _model-formsets:
+
+Model formsets
+==============
+
+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
+ >>> 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::
+ ``modelformset_factory`` uses ``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
+
+ 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',))
+
+.. _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).
+
+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
+---------------------------------------
+
+.. versionchanged:: 1.2
+
+As with regular formsets, you can use the ``max_num`` and ``extra`` parameters
+to ``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.forms:
+ ... 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>
+
+.. versionchanged:: 1.2
+
+A ``max_num`` value of ``None`` (the default) puts no limit on the number of
+forms displayed.
+
+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::
+
+ 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 overide the ``clean()`` method
+on a ``model_formset`` and maintain this validation, you must call the parent
+class's ``clean`` method::
+
+ 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
+
+Using a custom queryset
+-----------------------
+
+As stated earlier, you can override the default queryset used by the model
+formset::
+
+ 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.forms %}
+ {{ 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.forms %}
+ {% 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.forms %}
+ {{ 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 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::
+
+ 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::
+ ``inlineformset_factory`` uses ``modelformset_factory`` and marks
+ ``can_delete=True``.
+
+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 ``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.
+ 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.