| ========================== |
| 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`` |
| =============================== ======================================== |
| |
| .. 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.):: |
| |
| 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()) |
| |
| 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. The order in which the fields names are specified |
| in that list is respected when the form renders them. |
| |
| 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 |
| ---------------------------- |
| |
| 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: |
| ... 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 %} |
| {{ 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 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. |