Author: brosner
Date: 2008-12-08 18:36:25 -0600 (Mon, 08 Dec 2008)
New Revision: 9615
Modified:
django/branches/releases/1.0.X/docs/topics/forms/modelforms.txt
Log:
[1.0.X] Improved the model formset and inline formset documentation to be more
explicit and handle some cases that were never addressed before.
Backport of r9614 from trunk.
Modified: django/branches/releases/1.0.X/docs/topics/forms/modelforms.txt
===================================================================
--- django/branches/releases/1.0.X/docs/topics/forms/modelforms.txt
2008-12-09 00:31:17 UTC (rev 9614)
+++ django/branches/releases/1.0.X/docs/topics/forms/modelforms.txt
2008-12-09 00:36:25 UTC (rev 9615)
@@ -530,7 +530,7 @@
# do something.
else:
formset = AuthorFormSet()
- render_to_response("manage_authors.html", {
+ return render_to_response("manage_authors.html", {
"formset": formset,
})
@@ -539,13 +539,92 @@
data into the database. This is described above in
:ref:`saving-objects-in-the-formset`.
-Using ``inlineformset_factory``
--------------------------------
+Using a custom queryset
+~~~~~~~~~~~~~~~~~~~~~~~
-The ``inlineformset_factory`` is a helper to a common usage pattern of working
-with related objects through a foreign key. It takes all the same options as
-a ``modelformset_factory``. Suppose you have these two models::
+As stated earlier you can override the default queryset the model formset
+uses::
+ 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,
+ })
+
+What is critical to point out here is that you must pass the queryset in both
+the ``POST`` and ``GET`` cases shown above.
+
+Using the formset in the template
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are three ways you might want to render the formset in your template.
+You can let the formset do most of the work::
+
+ <form method="POST" action="">
+ {{ formset }}
+ </form>
+
+You can manually render the formset, but let the form deal with it self::
+
+ <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. Also see the :ref:`management form documentation
<understanding-the-managementform>`.
+
+Or you can just do it all yourself::
+
+ <form method="POST" action="">
+ {{ formset.management_form }}
+ {% for form in formset.formset %}
+ {% for fields in form %}
+ {{ field }}
+ {% endfor %}
+ {% endfor %}
+ </form>
+
+It is critical to note that if you opt to do most of the work yourself and you
+don't go with a field ``{% for %}`` loop of the form, as shown in the last
+example, you need to render to the primary key field. For example if you were
+to render just the ``name`` and ``age`` fields of a model::
+
+ <form method="POST" action="">
+ {{ formset.management_form }}
+ {% for form in formset.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 will ensure
+the model formset, in the ``POST`` case, will work correctly. The above
+example is assuming a primary key named ``id`` which is the name of the
+implicit primary key Django creates for you when one isn't given. If you have
+explicitly defined your own primary key field just make sure it gets rendered
+(it is likely to be a visible field anyway).
+
+Inline Formsets
+===============
+
+Inline formsets is a small abstraction layer on top of model formsets. It
+simplifies 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)
@@ -554,7 +633,7 @@
title = models.CharField(max_length=100)
If you want to create a formset that allows you to edit books belonging to
-some author you would do::
+some author you might do::
>>> from django.forms.models import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book)
@@ -566,7 +645,7 @@
``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 will
need to resolve the ambiguity manually using ``fk_name``. Given the following
@@ -580,3 +659,27 @@
To resolve this you can simply use ``fk_name`` to ``inlineformset_factory``::
>>> FrienshipFormSet = 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 some model. Here is how you might construct this view::
+
+ 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 the instance in both the ``POST`` and ``GET`` cases. This
+is required similiar to model formsets since the ``instance`` is simply used
+to create the queryset for the model formset that lives underneath.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---