summaryrefslogtreecommitdiff
path: root/parts/django/docs/topics/forms
diff options
context:
space:
mode:
Diffstat (limited to 'parts/django/docs/topics/forms')
-rw-r--r--parts/django/docs/topics/forms/formsets.txt440
-rw-r--r--parts/django/docs/topics/forms/index.txt402
-rw-r--r--parts/django/docs/topics/forms/media.txt309
-rw-r--r--parts/django/docs/topics/forms/modelforms.txt885
4 files changed, 0 insertions, 2036 deletions
diff --git a/parts/django/docs/topics/forms/formsets.txt b/parts/django/docs/topics/forms/formsets.txt
deleted file mode 100644
index 72296bc..0000000
--- a/parts/django/docs/topics/forms/formsets.txt
+++ /dev/null
@@ -1,440 +0,0 @@
-.. _formsets:
-
-Formsets
-========
-
-A formset is a layer of abstraction to working with multiple forms on the same
-page. It can be best compared to a data grid. Let's say you have the following
-form::
-
- >>> from django import forms
- >>> class ArticleForm(forms.Form):
- ... title = forms.CharField()
- ... pub_date = forms.DateField()
-
-You might want to allow the user to create several articles at once. To create
-a formset out of an ``ArticleForm`` you would do::
-
- >>> from django.forms.formsets import formset_factory
- >>> ArticleFormSet = formset_factory(ArticleForm)
-
-You now have created a formset named ``ArticleFormSet``. The formset gives you
-the ability to iterate over the forms in the formset and display them as you
-would with a regular form::
-
- >>> formset = ArticleFormSet()
- >>> for form in formset.forms:
- ... print form.as_table()
- <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
- <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>
-
-As you can see it only displayed one empty form. The number of empty forms
-that is displayed is controlled by the ``extra`` parameter. By default,
-``formset_factory`` defines one extra form; the following example will
-display two blank forms::
-
- >>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
-
-Using initial data with a formset
----------------------------------
-
-Initial data is what drives the main usability of a formset. As shown above
-you can define the number of extra forms. What this means is that you are
-telling the formset how many additional forms to show in addition to the
-number of forms it generates from the initial data. Lets take a look at an
-example::
-
- >>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
- >>> formset = ArticleFormSet(initial=[
- ... {'title': u'Django is now open source',
- ... 'pub_date': datetime.date.today()},
- ... ])
-
- >>> for form in formset.forms:
- ... print form.as_table()
- <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr>
- <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr>
- <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr>
- <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr>
- <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
- <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>
-
-There are now a total of three forms showing above. One for the initial data
-that was passed in and two extra forms. Also note that we are passing in a
-list of dictionaries as the initial data.
-
-.. seealso::
-
- :ref:`Creating formsets from models with model formsets <model-formsets>`.
-
-.. _formsets-max-num:
-
-Limiting the maximum number of forms
-------------------------------------
-
-The ``max_num`` parameter to ``formset_factory`` gives you the ability to
-limit the maximum number of empty forms the formset will display::
-
- >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
- >>> formset = ArticleFormset()
- >>> for form in formset.forms:
- ... print form.as_table()
- <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
- <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>
-
-.. versionchanged:: 1.2
-
-If the value of ``max_num`` is greater than the number of existing
-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``.
-
-A ``max_num`` value of ``None`` (the default) puts no limit on the number of
-forms displayed. Please note that the default value of ``max_num`` was changed
-from ``0`` to ``None`` in version 1.2 to allow ``0`` as a valid value.
-
-Formset validation
-------------------
-
-Validation with a formset is almost identical to a regular ``Form``. There is
-an ``is_valid`` method on the formset to provide a convenient way to validate
-all forms in the formset::
-
- >>> ArticleFormSet = formset_factory(ArticleForm)
- >>> formset = ArticleFormSet({})
- >>> formset.is_valid()
- True
-
-We passed in no data to the formset which is resulting in a valid form. The
-formset is smart enough to ignore extra forms that were not changed. If we
-provide an invalid article::
-
- >>> data = {
- ... 'form-TOTAL_FORMS': u'2',
- ... 'form-INITIAL_FORMS': u'0',
- ... 'form-MAX_NUM_FORMS': u'',
- ... 'form-0-title': u'Test',
- ... 'form-0-pub_date': u'16 June 1904',
- ... 'form-1-title': u'Test',
- ... 'form-1-pub_date': u'', # <-- this date is missing but required
- ... }
- >>> formset = ArticleFormSet(data)
- >>> formset.is_valid()
- False
- >>> formset.errors
- [{}, {'pub_date': [u'This field is required.']}]
-
-As we can see, ``formset.errors`` is a list whose entries correspond to the
-forms in the formset. Validation was performed for each of the two forms, and
-the expected error message appears for the second item.
-
-.. _understanding-the-managementform:
-
-Understanding the ManagementForm
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You may have noticed the additional data (``form-TOTAL_FORMS``,
-``form-INITIAL_FORMS`` and ``form-MAX_NUM_FORMS``) that was required
-in the formset's data above. This data is required for the
-``ManagementForm``. This form is used by the formset to manage the
-collection of forms contained in the formset. If you don't provide
-this management data, an exception will be raised::
-
- >>> data = {
- ... 'form-0-title': u'Test',
- ... 'form-0-pub_date': u'',
- ... }
- >>> formset = ArticleFormSet(data)
- Traceback (most recent call last):
- ...
- django.forms.util.ValidationError: [u'ManagementForm data is missing or has been tampered with']
-
-It is used to keep track of how many form instances are being displayed. If
-you are adding new forms via JavaScript, you should increment the count fields
-in this form as well.
-
-The management form is available as an attribute of the formset
-itself. When rendering a formset in a template, you can include all
-the management data by rendering ``{{ my_formset.management_form }}``
-(substituting the name of your formset as appropriate).
-
-.. versionadded:: 1.1
-
-``total_form_count`` and ``initial_form_count``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``BaseFormSet`` has a couple of methods that are closely related to the
-``ManagementForm``, ``total_form_count`` and ``initial_form_count``.
-
-``total_form_count`` returns the total number of forms in this formset.
-``initial_form_count`` returns the number of forms in the formset that were
-pre-filled, and is also used to determine how many forms are required. You
-will probably never need to override either of these methods, so please be
-sure you understand what they do before doing so.
-
-.. versionadded:: 1.2
-
-``empty_form``
-~~~~~~~~~~~~~~
-
-``BaseFormSet`` provides an additional attribute ``empty_form`` which returns
-a form instance with a prefix of ``__prefix__`` for easier use in dynamic
-forms with JavaScript.
-
-Custom formset validation
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A formset has a ``clean`` method similar to the one on a ``Form`` class. This
-is where you define your own validation that works at the formset level::
-
- >>> from django.forms.formsets import BaseFormSet
-
- >>> class BaseArticleFormSet(BaseFormSet):
- ... def clean(self):
- ... """Checks that no two articles have the same title."""
- ... if any(self.errors):
- ... # Don't bother validating the formset unless each form is valid on its own
- ... return
- ... titles = []
- ... for i in range(0, self.total_form_count()):
- ... form = self.forms[i]
- ... title = form.cleaned_data['title']
- ... if title in titles:
- ... raise forms.ValidationError, "Articles in a set must have distinct titles."
- ... titles.append(title)
-
- >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet)
- >>> data = {
- ... 'form-TOTAL_FORMS': u'2',
- ... 'form-INITIAL_FORMS': u'0',
- ... 'form-MAX_NUM_FORMS': u'',
- ... 'form-0-title': u'Test',
- ... 'form-0-pub_date': u'16 June 1904',
- ... 'form-1-title': u'Test',
- ... 'form-1-pub_date': u'23 June 1912',
- ... }
- >>> formset = ArticleFormSet(data)
- >>> formset.is_valid()
- False
- >>> formset.errors
- [{}, {}]
- >>> formset.non_form_errors()
- [u'Articles in a set must have distinct titles.']
-
-The formset ``clean`` method is called after all the ``Form.clean`` methods
-have been called. The errors will be found using the ``non_form_errors()``
-method on the formset.
-
-Dealing with ordering and deletion of forms
--------------------------------------------
-
-Common use cases with a formset is dealing with ordering and deletion of the
-form instances. This has been dealt with for you. The ``formset_factory``
-provides two optional parameters ``can_order`` and ``can_delete`` that will do
-the extra work of adding the extra fields and providing simpler ways of
-getting to that data.
-
-``can_order``
-~~~~~~~~~~~~~
-
-Default: ``False``
-
-Lets create a formset with the ability to order::
-
- >>> ArticleFormSet = formset_factory(ArticleForm, can_order=True)
- >>> formset = ArticleFormSet(initial=[
- ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
- ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
- ... ])
- >>> for form in formset.forms:
- ... print form.as_table()
- <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr>
- <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr>
- <tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="text" name="form-0-ORDER" value="1" id="id_form-0-ORDER" /></td></tr>
- <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr>
- <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr>
- <tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="text" name="form-1-ORDER" value="2" id="id_form-1-ORDER" /></td></tr>
- <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
- <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>
- <tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="text" name="form-2-ORDER" id="id_form-2-ORDER" /></td></tr>
-
-This adds an additional field to each form. This new field is named ``ORDER``
-and is an ``forms.IntegerField``. For the forms that came from the initial
-data it automatically assigned them a numeric value. Lets look at what will
-happen when the user changes these values::
-
- >>> data = {
- ... 'form-TOTAL_FORMS': u'3',
- ... 'form-INITIAL_FORMS': u'2',
- ... 'form-MAX_NUM_FORMS': u'',
- ... 'form-0-title': u'Article #1',
- ... 'form-0-pub_date': u'2008-05-10',
- ... 'form-0-ORDER': u'2',
- ... 'form-1-title': u'Article #2',
- ... 'form-1-pub_date': u'2008-05-11',
- ... 'form-1-ORDER': u'1',
- ... 'form-2-title': u'Article #3',
- ... 'form-2-pub_date': u'2008-05-01',
- ... 'form-2-ORDER': u'0',
- ... }
-
- >>> formset = ArticleFormSet(data, initial=[
- ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
- ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
- ... ])
- >>> formset.is_valid()
- True
- >>> for form in formset.ordered_forms:
- ... print form.cleaned_data
- {'pub_date': datetime.date(2008, 5, 1), 'ORDER': 0, 'title': u'Article #3'}
- {'pub_date': datetime.date(2008, 5, 11), 'ORDER': 1, 'title': u'Article #2'}
- {'pub_date': datetime.date(2008, 5, 10), 'ORDER': 2, 'title': u'Article #1'}
-
-``can_delete``
-~~~~~~~~~~~~~~
-
-Default: ``False``
-
-Lets create a formset with the ability to delete::
-
- >>> ArticleFormSet = formset_factory(ArticleForm, can_delete=True)
- >>> formset = ArticleFormSet(initial=[
- ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
- ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
- ... ])
- >>> for form in formset.forms:
- .... print form.as_table()
- <input type="hidden" name="form-TOTAL_FORMS" value="3" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="2" 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-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr>
- <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr>
- <tr><th><label for="id_form-0-DELETE">Delete:</label></th><td><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE" /></td></tr>
- <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr>
- <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr>
- <tr><th><label for="id_form-1-DELETE">Delete:</label></th><td><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE" /></td></tr>
- <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
- <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>
- <tr><th><label for="id_form-2-DELETE">Delete:</label></th><td><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE" /></td></tr>
-
-Similar to ``can_order`` this adds a new field to each form named ``DELETE``
-and is a ``forms.BooleanField``. When data comes through marking any of the
-delete fields you can access them with ``deleted_forms``::
-
- >>> data = {
- ... 'form-TOTAL_FORMS': u'3',
- ... 'form-INITIAL_FORMS': u'2',
- ... 'form-MAX_NUM_FORMS': u'',
- ... 'form-0-title': u'Article #1',
- ... 'form-0-pub_date': u'2008-05-10',
- ... 'form-0-DELETE': u'on',
- ... 'form-1-title': u'Article #2',
- ... 'form-1-pub_date': u'2008-05-11',
- ... 'form-1-DELETE': u'',
- ... 'form-2-title': u'',
- ... 'form-2-pub_date': u'',
- ... 'form-2-DELETE': u'',
- ... }
-
- >>> formset = ArticleFormSet(data, initial=[
- ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
- ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
- ... ])
- >>> [form.cleaned_data for form in formset.deleted_forms]
- [{'DELETE': True, 'pub_date': datetime.date(2008, 5, 10), 'title': u'Article #1'}]
-
-Adding additional fields to a formset
--------------------------------------
-
-If you need to add additional fields to the formset this can be easily
-accomplished. The formset base class provides an ``add_fields`` method. You
-can simply override this method to add your own fields or even redefine the
-default fields/attributes of the order and deletion fields::
-
- >>> class BaseArticleFormSet(BaseFormSet):
- ... def add_fields(self, form, index):
- ... super(BaseArticleFormSet, self).add_fields(form, index)
- ... form.fields["my_field"] = forms.CharField()
-
- >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet)
- >>> formset = ArticleFormSet()
- >>> for form in formset.forms:
- ... print form.as_table()
- <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
- <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>
- <tr><th><label for="id_form-0-my_field">My field:</label></th><td><input type="text" name="form-0-my_field" id="id_form-0-my_field" /></td></tr>
-
-Using a formset in views and templates
---------------------------------------
-
-Using a formset inside a view is as easy as using a regular ``Form`` class.
-The only thing you will want to be aware of is making sure to use the
-management form inside the template. Let's look at a sample view:
-
-.. code-block:: python
-
- def manage_articles(request):
- ArticleFormSet = formset_factory(ArticleForm)
- if request.method == 'POST':
- formset = ArticleFormSet(request.POST, request.FILES)
- if formset.is_valid():
- # do something with the formset.cleaned_data
- pass
- else:
- formset = ArticleFormSet()
- return render_to_response('manage_articles.html', {'formset': formset})
-
-The ``manage_articles.html`` template might look like this:
-
-.. code-block:: html+django
-
- <form method="post" action="">
- {{ formset.management_form }}
- <table>
- {% for form in formset.forms %}
- {{ form }}
- {% endfor %}
- </table>
- </form>
-
-However the above can be slightly shortcutted and let the formset itself deal
-with the management form:
-
-.. code-block:: html+django
-
- <form method="post" action="">
- <table>
- {{ formset }}
- </table>
- </form>
-
-The above ends up calling the ``as_table`` method on the formset class.
-
-Using more than one formset in a view
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You are able to use more than one formset in a view if you like. Formsets
-borrow much of its behavior from forms. With that said you are able to use
-``prefix`` to prefix formset form field names with a given value to allow
-more than one formset to be sent to a view without name clashing. Lets take
-a look at how this might be accomplished:
-
-.. code-block:: python
-
- def manage_articles(request):
- ArticleFormSet = formset_factory(ArticleForm)
- BookFormSet = formset_factory(BookForm)
- if request.method == 'POST':
- article_formset = ArticleFormSet(request.POST, request.FILES, prefix='articles')
- book_formset = BookFormSet(request.POST, request.FILES, prefix='books')
- if article_formset.is_valid() and book_formset.is_valid():
- # do something with the cleaned_data on the formsets.
- pass
- else:
- article_formset = ArticleFormSet(prefix='articles')
- book_formset = BookFormSet(prefix='books')
- return render_to_response('manage_articles.html', {
- 'article_formset': article_formset,
- 'book_formset': book_formset,
- })
-
-You would then render the formsets as normal. It is important to point out
-that you need to pass ``prefix`` on both the POST and non-POST cases so that
-it is rendered and processed correctly.
diff --git a/parts/django/docs/topics/forms/index.txt b/parts/django/docs/topics/forms/index.txt
deleted file mode 100644
index 30b09c0..0000000
--- a/parts/django/docs/topics/forms/index.txt
+++ /dev/null
@@ -1,402 +0,0 @@
-==================
-Working with forms
-==================
-
-.. admonition:: About this document
-
- This document provides an introduction to Django's form handling features.
- For a more detailed look at specific areas of the forms API, see
- :doc:`/ref/forms/api`, :doc:`/ref/forms/fields`, and
- :doc:`/ref/forms/validation`.
-
-.. highlightlang:: html+django
-
-``django.forms`` is Django's form-handling library.
-
-While it is possible to process form submissions just using Django's
-:class:`~django.http.HttpRequest` class, using the form library takes care of a
-number of common form-related tasks. Using it, you can:
-
- 1. Display an HTML form with automatically generated form widgets.
- 2. Check submitted data against a set of validation rules.
- 3. Redisplay a form in the case of validation errors.
- 4. Convert submitted form data to the relevant Python data types.
-
-Overview
-========
-
-The library deals with these concepts:
-
-.. glossary::
-
- Widget
- A class that corresponds to an HTML form widget, e.g.
- ``<input type="text">`` or ``<textarea>``. This handles rendering of the
- widget as HTML.
-
- Field
- A class that is responsible for doing validation, e.g.
- an ``EmailField`` that makes sure its data is a valid e-mail address.
-
- Form
- A collection of fields that knows how to validate itself and
- display itself as HTML.
-
- Form Media
- The CSS and JavaScript resources that are required to render a form.
-
-The library is decoupled from the other Django components, such as the database
-layer, views and templates. It relies only on Django settings, a couple of
-``django.utils`` helper functions and Django's internationalization hooks (but
-you're not required to be using internationalization features to use this
-library).
-
-Form objects
-============
-
-A Form object encapsulates a sequence of form fields and a collection of
-validation rules that must be fulfilled in order for the form to be accepted.
-Form classes are created as subclasses of ``django.forms.Form`` and
-make use of a declarative style that you'll be familiar with if you've used
-Django's database models.
-
-For example, consider a form used to implement "contact me" functionality on a
-personal Web site:
-
-.. code-block:: python
-
- from django import forms
-
- class ContactForm(forms.Form):
- subject = forms.CharField(max_length=100)
- message = forms.CharField()
- sender = forms.EmailField()
- cc_myself = forms.BooleanField(required=False)
-
-A form is composed of ``Field`` objects. In this case, our form has four
-fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. ``CharField``,
-``EmailField`` and ``BooleanField`` are just three of the available field types;
-a full list can be found in :doc:`/ref/forms/fields`.
-
-If your form is going to be used to directly add or edit a Django model, you can
-use a :doc:`ModelForm </topics/forms/modelforms>` to avoid duplicating your model
-description.
-
-Using a form in a view
-----------------------
-
-The standard pattern for processing a form in a view looks like this:
-
-.. code-block:: python
-
- def contact(request):
- if request.method == 'POST': # If the form has been submitted...
- form = ContactForm(request.POST) # A form bound to the POST data
- if form.is_valid(): # All validation rules pass
- # Process the data in form.cleaned_data
- # ...
- return HttpResponseRedirect('/thanks/') # Redirect after POST
- else:
- form = ContactForm() # An unbound form
-
- return render_to_response('contact.html', {
- 'form': form,
- })
-
-
-There are three code paths here:
-
- 1. If the form has not been submitted, an unbound instance of ContactForm is
- created and passed to the template.
- 2. If the form has been submitted, a bound instance of the form is created
- using ``request.POST``. If the submitted data is valid, it is processed
- and the user is re-directed to a "thanks" page.
- 3. If the form has been submitted but is invalid, the bound form instance is
- passed on to the template.
-
-.. versionchanged:: 1.0
- The ``cleaned_data`` attribute was called ``clean_data`` in earlier releases.
-
-The distinction between **bound** and **unbound** forms is important. An unbound
-form does not have any data associated with it; when rendered to the user, it
-will be empty or will contain default values. A bound form does have submitted
-data, and hence can be used to tell if that data is valid. If an invalid bound
-form is rendered it can include inline error messages telling the user where
-they went wrong.
-
-See :ref:`ref-forms-api-bound-unbound` for further information on the
-differences between bound and unbound forms.
-
-Handling file uploads with a form
----------------------------------
-
-To see how to handle file uploads with your form see
-:ref:`binding-uploaded-files` for more information.
-
-Processing the data from a form
--------------------------------
-
-Once ``is_valid()`` returns ``True``, you can process the form submission safe
-in the knowledge that it conforms to the validation rules defined by your form.
-While you could access ``request.POST`` directly at this point, it is better to
-access ``form.cleaned_data``. This data has not only been validated but will
-also be converted in to the relevant Python types for you. In the above example,
-``cc_myself`` will be a boolean value. Likewise, fields such as ``IntegerField``
-and ``FloatField`` convert values to a Python int and float respectively.
-
-Extending the above example, here's how the form data could be processed:
-
-.. code-block:: python
-
- if form.is_valid():
- subject = form.cleaned_data['subject']
- message = form.cleaned_data['message']
- sender = form.cleaned_data['sender']
- cc_myself = form.cleaned_data['cc_myself']
-
- recipients = ['info@example.com']
- if cc_myself:
- recipients.append(sender)
-
- from django.core.mail import send_mail
- send_mail(subject, message, sender, recipients)
- return HttpResponseRedirect('/thanks/') # Redirect after POST
-
-For more on sending e-mail from Django, see :doc:`/topics/email`.
-
-Displaying a form using a template
-----------------------------------
-
-Forms are designed to work with the Django template language. In the above
-example, we passed our ``ContactForm`` instance to the template using the
-context variable ``form``. Here's a simple example template::
-
- <form action="/contact/" method="post">
- {{ form.as_p }}
- <input type="submit" value="Submit" />
- </form>
-
-The form only outputs its own fields; it is up to you to provide the surrounding
-``<form>`` tags and the submit button.
-
-``form.as_p`` will output the form with each form field and accompanying label
-wrapped in a paragraph. Here's the output for our example template::
-
- <form action="/contact/" method="post">
- <p><label for="id_subject">Subject:</label>
- <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
- <p><label for="id_message">Message:</label>
- <input type="text" name="message" id="id_message" /></p>
- <p><label for="id_sender">Sender:</label>
- <input type="text" name="sender" id="id_sender" /></p>
- <p><label for="id_cc_myself">Cc myself:</label>
- <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
- <input type="submit" value="Submit" />
- </form>
-
-Note that each form field has an ID attribute set to ``id_<field-name>``, which
-is referenced by the accompanying label tag. This is important for ensuring
-forms are accessible to assistive technology such as screen reader software. You
-can also :ref:`customize the way in which labels and ids are generated
-<ref-forms-api-configuring-label>`.
-
-You can also use ``form.as_table`` to output table rows (you'll need to provide
-your own ``<table>`` tags) and ``form.as_ul`` to output list items.
-
-Customizing the form template
------------------------------
-
-If the default generated HTML is not to your taste, you can completely customize
-the way a form is presented using the Django template language. Extending the
-above example::
-
- <form action="/contact/" method="post">
- {{ form.non_field_errors }}
- <div class="fieldWrapper">
- {{ form.subject.errors }}
- <label for="id_subject">E-mail subject:</label>
- {{ form.subject }}
- </div>
- <div class="fieldWrapper">
- {{ form.message.errors }}
- <label for="id_message">Your message:</label>
- {{ form.message }}
- </div>
- <div class="fieldWrapper">
- {{ form.sender.errors }}
- <label for="id_sender">Your email address:</label>
- {{ form.sender }}
- </div>
- <div class="fieldWrapper">
- {{ form.cc_myself.errors }}
- <label for="id_cc_myself">CC yourself?</label>
- {{ form.cc_myself }}
- </div>
- <p><input type="submit" value="Send message" /></p>
- </form>
-
-Each named form-field can be output to the template using
-``{{ form.name_of_field }}``, which will produce the HTML needed to display the
-form widget. Using ``{{ form.name_of_field.errors }}`` displays a list of form
-errors, rendered as an unordered list. This might look like::
-
- <ul class="errorlist">
- <li>Sender is required.</li>
- </ul>
-
-The list has a CSS class of ``errorlist`` to allow you to style its appearance.
-If you wish to further customize the display of errors you can do so by looping
-over them::
-
- {% if form.subject.errors %}
- <ol>
- {% for error in form.subject.errors %}
- <li><strong>{{ error|escape }}</strong></li>
- {% endfor %}
- </ol>
- {% endif %}
-
-Looping over the form's fields
-------------------------------
-
-If you're using the same HTML for each of your form fields, you can reduce
-duplicate code by looping through each field in turn using a ``{% for %}``
-loop::
-
- <form action="/contact/" method="post">
- {% for field in form %}
- <div class="fieldWrapper">
- {{ field.errors }}
- {{ field.label_tag }}: {{ field }}
- </div>
- {% endfor %}
- <p><input type="submit" value="Send message" /></p>
- </form>
-
-Within this loop, ``{{ field }}`` is an instance of :class:`BoundField`.
-``BoundField`` also has the following attributes, which can be useful in your
-templates:
-
- ``{{ field.label }}``
- The label of the field, e.g. ``E-mail address``.
-
- ``{{ field.label_tag }}``
- The field's label wrapped in the appropriate HTML ``<label>`` tag,
- e.g. ``<label for="id_email">E-mail address</label>``
-
- ``{{ field.html_name }}``
- The name of the field that will be used in the input element's name
- field. This takes the form prefix into account, if it has been set.
-
- ``{{ field.help_text }}``
- Any help text that has been associated with the field.
-
- ``{{ field.errors }}``
- Outputs a ``<ul class="errorlist">`` containing any validation errors
- corresponding to this field. You can customize the presentation of
- the errors with a ``{% for error in field.errors %}`` loop. In this
- case, each object in the loop is a simple string containing the error
- message.
-
- ``field.is_hidden``
- This attribute is ``True`` if the form field is a hidden field and
- ``False`` otherwise. It's not particularly useful as a template
- variable, but could be useful in conditional tests such as::
-
- {% if field.is_hidden %}
- {# Do something special #}
- {% endif %}
-
-Looping over hidden and visible fields
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you're manually laying out a form in a template, as opposed to relying on
-Django's default form layout, you might want to treat ``<input type="hidden">``
-fields differently than non-hidden fields. For example, because hidden fields
-don't display anything, putting error messages "next to" the field could cause
-confusion for your users -- so errors for those fields should be handled
-differently.
-
-Django provides two methods on a form that allow you to loop over the hidden
-and visible fields independently: ``hidden_fields()`` and
-``visible_fields()``. Here's a modification of an earlier example that uses
-these two methods::
-
- <form action="/contact/" method="post">
- {% for field in form.visible_fields %}
- <div class="fieldWrapper">
-
- {# Include the hidden fields in the form #}
- {% if forloop.first %}
- {% for hidden in form.hidden_fields %}
- {{ hidden }}
- {% endfor %}
- {% endif %}
-
- {{ field.errors }}
- {{ field.label_tag }}: {{ field }}
- </div>
- {% endfor %}
- <p><input type="submit" value="Send message" /></p>
- </form>
-
-This example does not handle any errors in the hidden fields. Usually, an
-error in a hidden field is a sign of form tampering, since normal form
-interaction won't alter them. However, you could easily insert some error
-displays for those form errors, as well.
-
-.. versionadded:: 1.1
- The ``hidden_fields`` and ``visible_fields`` methods are new in Django
- 1.1.
-
-Reusable form templates
------------------------
-
-If your site uses the same rendering logic for forms in multiple places, you
-can reduce duplication by saving the form's loop in a standalone template and
-using the :ttag:`include` tag to reuse it in other templates::
-
- <form action="/contact/" method="post">
- {% include "form_snippet.html" %}
- <p><input type="submit" value="Send message" /></p>
- </form>
-
- # In form_snippet.html:
-
- {% for field in form %}
- <div class="fieldWrapper">
- {{ field.errors }}
- {{ field.label_tag }}: {{ field }}
- </div>
- {% endfor %}
-
-If the form object passed to a template has a different name within the
-context, you can alias it using the :ttag:`with` tag::
-
- <form action="/comments/add/" method="post">
- {% with comment_form as form %}
- {% include "form_snippet.html" %}
- {% endwith %}
- <p><input type="submit" value="Submit comment" /></p>
- </form>
-
-If you find yourself doing this often, you might consider creating a custom
-:ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`.
-
-Further topics
-==============
-
-This covers the basics, but forms can do a whole lot more:
-
-.. toctree::
- :maxdepth: 2
-
- modelforms
- formsets
- media
-
-.. seealso::
-
- :doc:`The Forms Reference </ref/forms/index>`
- Covers the full API reference, including form fields, form widgets,
- and form and field validation.
diff --git a/parts/django/docs/topics/forms/media.txt b/parts/django/docs/topics/forms/media.txt
deleted file mode 100644
index fe70894..0000000
--- a/parts/django/docs/topics/forms/media.txt
+++ /dev/null
@@ -1,309 +0,0 @@
-Form Media
-==========
-
-Rendering an attractive and easy-to-use Web form requires more than just
-HTML - it also requires CSS stylesheets, and if you want to use fancy
-"Web2.0" widgets, you may also need to include some JavaScript on each
-page. The exact combination of CSS and JavaScript that is required for
-any given page will depend upon the widgets that are in use on that page.
-
-This is where Django media definitions come in. Django allows you to
-associate different media files with the forms and widgets that require
-that media. For example, if you want to use a calendar to render DateFields,
-you can define a custom Calendar widget. This widget can then be associated
-with the CSS and JavaScript that is required to render the calendar. When
-the Calendar widget is used on a form, Django is able to identify the CSS and
-JavaScript files that are required, and provide the list of file names
-in a form suitable for easy inclusion on your Web page.
-
-.. admonition:: Media and Django Admin
-
- The Django Admin application defines a number of customized widgets
- for calendars, filtered selections, and so on. These widgets define
- media requirements, and the Django Admin uses the custom widgets
- in place of the Django defaults. The Admin templates will only include
- those media files that are required to render the widgets on any
- given page.
-
- If you like the widgets that the Django Admin application uses,
- feel free to use them in your own application! They're all stored
- in ``django.contrib.admin.widgets``.
-
-.. admonition:: Which JavaScript toolkit?
-
- Many JavaScript toolkits exist, and many of them include widgets (such
- as calendar widgets) that can be used to enhance your application.
- Django has deliberately avoided blessing any one JavaScript toolkit.
- Each toolkit has its own relative strengths and weaknesses - use
- whichever toolkit suits your requirements. Django is able to integrate
- with any JavaScript toolkit.
-
-Media as a static definition
-----------------------------
-
-The easiest way to define media is as a static definition. Using this method,
-the media declaration is an inner class. The properties of the inner class
-define the media requirements.
-
-Here's a simple example::
-
- class CalendarWidget(forms.TextInput):
- class Media:
- css = {
- 'all': ('pretty.css',)
- }
- js = ('animations.js', 'actions.js')
-
-This code defines a ``CalendarWidget``, which will be based on ``TextInput``.
-Every time the CalendarWidget is used on a form, that form will be directed
-to include the CSS file ``pretty.css``, and the JavaScript files
-``animations.js`` and ``actions.js``.
-
-This static media definition is converted at runtime into a widget property
-named ``media``. The media for a CalendarWidget instance can be retrieved
-through this property::
-
- >>> w = CalendarWidget()
- >>> print w.media
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://media.example.com/actions.js"></script>
-
-Here's a list of all possible ``Media`` options. There are no required options.
-
-``css``
-~~~~~~~
-
-A dictionary describing the CSS files required for various forms of output
-media.
-
-The values in the dictionary should be a tuple/list of file names. See
-`the section on media paths`_ for details of how to specify paths to media
-files.
-
-.. _the section on media paths: `Paths in media definitions`_
-
-The keys in the dictionary are the output media types. These are the same
-types accepted by CSS files in media declarations: 'all', 'aural', 'braille',
-'embossed', 'handheld', 'print', 'projection', 'screen', 'tty' and 'tv'. If
-you need to have different stylesheets for different media types, provide
-a list of CSS files for each output medium. The following example would
-provide two CSS options -- one for the screen, and one for print::
-
- class Media:
- css = {
- 'screen': ('pretty.css',),
- 'print': ('newspaper.css',)
- }
-
-If a group of CSS files are appropriate for multiple output media types,
-the dictionary key can be a comma separated list of output media types.
-In the following example, TV's and projectors will have the same media
-requirements::
-
- class Media:
- css = {
- 'screen': ('pretty.css',),
- 'tv,projector': ('lo_res.css',),
- 'print': ('newspaper.css',)
- }
-
-If this last CSS definition were to be rendered, it would become the following HTML::
-
- <link href="http://media.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
- <link href="http://media.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
- <link href="http://media.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />
-
-``js``
-~~~~~~
-
-A tuple describing the required JavaScript files. See
-`the section on media paths`_ for details of how to specify paths to media
-files.
-
-``extend``
-~~~~~~~~~~
-
-A boolean defining inheritance behavior for media declarations.
-
-By default, any object using a static media definition will inherit all the
-media associated with the parent widget. This occurs regardless of how the
-parent defines its media requirements. For example, if we were to extend our
-basic Calendar widget from the example above::
-
- >>> class FancyCalendarWidget(CalendarWidget):
- ... class Media:
- ... css = {
- ... 'all': ('fancy.css',)
- ... }
- ... js = ('whizbang.js',)
-
- >>> w = FancyCalendarWidget()
- >>> print w.media
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://media.example.com/actions.js"></script>
- <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
-
-The FancyCalendar widget inherits all the media from it's parent widget. If
-you don't want media to be inherited in this way, add an ``extend=False``
-declaration to the media declaration::
-
- >>> class FancyCalendarWidget(CalendarWidget):
- ... class Media:
- ... extend = False
- ... css = {
- ... 'all': ('fancy.css',)
- ... }
- ... js = ('whizbang.js',)
-
- >>> w = FancyCalendarWidget()
- >>> print w.media
- <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
-
-If you require even more control over media inheritance, define your media
-using a `dynamic property`_. Dynamic properties give you complete control over
-which media files are inherited, and which are not.
-
-.. _dynamic property: `Media as a dynamic property`_
-
-Media as a dynamic property
----------------------------
-
-If you need to perform some more sophisticated manipulation of media
-requirements, you can define the media property directly. This is done
-by defining a widget property that returns an instance of ``forms.Media``.
-The constructor for ``forms.Media`` accepts ``css`` and ``js`` keyword
-arguments in the same format as that used in a static media definition.
-
-For example, the static media definition for our Calendar Widget could
-also be defined in a dynamic fashion::
-
- class CalendarWidget(forms.TextInput):
- def _media(self):
- return forms.Media(css={'all': ('pretty.css',)},
- js=('animations.js', 'actions.js'))
- media = property(_media)
-
-See the section on `Media objects`_ for more details on how to construct
-return values for dynamic media properties.
-
-Paths in media definitions
---------------------------
-
-Paths used to specify media can be either relative or absolute. If a path
-starts with '/', 'http://' or 'https://', it will be interpreted as an absolute
-path, and left as-is. All other paths will be prepended with the value of
-``settings.MEDIA_URL``. For example, if the MEDIA_URL for your site was
-``http://media.example.com/``::
-
- class CalendarWidget(forms.TextInput):
- class Media:
- css = {
- 'all': ('/css/pretty.css',),
- }
- js = ('animations.js', 'http://othersite.com/actions.js')
-
- >>> w = CalendarWidget()
- >>> print w.media
- <link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://othersite.com/actions.js"></script>
-
-Media objects
--------------
-
-When you interrogate the media attribute of a widget or form, the value that
-is returned is a ``forms.Media`` object. As we have already seen, the string
-representation of a Media object is the HTML required to include media
-in the ``<head>`` block of your HTML page.
-
-However, Media objects have some other interesting properties.
-
-Media subsets
-~~~~~~~~~~~~~
-
-If you only want media of a particular type, you can use the subscript operator
-to filter out a medium of interest. For example::
-
- >>> w = CalendarWidget()
- >>> print w.media
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://media.example.com/actions.js"></script>
-
- >>> print w.media['css']
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
-
-When you use the subscript operator, the value that is returned is a new
-Media object -- but one that only contains the media of interest.
-
-Combining media objects
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Media objects can also be added together. When two media objects are added,
-the resulting Media object contains the union of the media from both files::
-
- >>> class CalendarWidget(forms.TextInput):
- ... class Media:
- ... css = {
- ... 'all': ('pretty.css',)
- ... }
- ... js = ('animations.js', 'actions.js')
-
- >>> class OtherWidget(forms.TextInput):
- ... class Media:
- ... js = ('whizbang.js',)
-
- >>> w1 = CalendarWidget()
- >>> w2 = OtherWidget()
- >>> print w1.media + w2.media
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://media.example.com/actions.js"></script>
- <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
-
-Media on Forms
---------------
-
-Widgets aren't the only objects that can have media definitions -- forms
-can also define media. The rules for media definitions on forms are the
-same as the rules for widgets: declarations can be static or dynamic;
-path and inheritance rules for those declarations are exactly the same.
-
-Regardless of whether you define a media declaration, *all* Form objects
-have a media property. The default value for this property is the result
-of adding the media definitions for all widgets that are part of the form::
-
- >>> class ContactForm(forms.Form):
- ... date = DateField(widget=CalendarWidget)
- ... name = CharField(max_length=40, widget=OtherWidget)
-
- >>> f = ContactForm()
- >>> f.media
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://media.example.com/actions.js"></script>
- <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
-
-If you want to associate additional media with a form -- for example, CSS for form
-layout -- simply add a media declaration to the form::
-
- >>> class ContactForm(forms.Form):
- ... date = DateField(widget=CalendarWidget)
- ... name = CharField(max_length=40, widget=OtherWidget)
- ...
- ... class Media:
- ... css = {
- ... 'all': ('layout.css',)
- ... }
-
- >>> f = ContactForm()
- >>> f.media
- <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <link href="http://media.example.com/layout.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
- <script type="text/javascript" src="http://media.example.com/actions.js"></script>
- <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
diff --git a/parts/django/docs/topics/forms/modelforms.txt b/parts/django/docs/topics/forms/modelforms.txt
deleted file mode 100644
index 23ed9a7..0000000
--- a/parts/django/docs/topics/forms/modelforms.txt
+++ /dev/null
@@ -1,885 +0,0 @@
-==========================
-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.