Improved the model formset and inline formset documentation to be more explicit and handle some cases that were never addressed before.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@9614 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
15bd649940
commit
6553ddc5b4
|
@ -530,7 +530,7 @@ formset to a user to edit ``Author`` model instances::
|
||||||
# do something.
|
# do something.
|
||||||
else:
|
else:
|
||||||
formset = AuthorFormSet()
|
formset = AuthorFormSet()
|
||||||
render_to_response("manage_authors.html", {
|
return render_to_response("manage_authors.html", {
|
||||||
"formset": formset,
|
"formset": formset,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -539,12 +539,91 @@ in a view. The only difference is that we call ``formset.save()`` to save the
|
||||||
data into the database. This is described above in
|
data into the database. This is described above in
|
||||||
:ref:`saving-objects-in-the-formset`.
|
: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
|
As stated earlier you can override the default queryset the model formset
|
||||||
with related objects through a foreign key. It takes all the same options as
|
uses::
|
||||||
a ``modelformset_factory``. Suppose you have these two models::
|
|
||||||
|
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):
|
class Author(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
|
@ -554,7 +633,7 @@ a ``modelformset_factory``. Suppose you have these two models::
|
||||||
title = models.CharField(max_length=100)
|
title = models.CharField(max_length=100)
|
||||||
|
|
||||||
If you want to create a formset that allows you to edit books belonging to
|
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
|
>>> from django.forms.models import inlineformset_factory
|
||||||
>>> BookFormSet = inlineformset_factory(Author, Book)
|
>>> BookFormSet = inlineformset_factory(Author, Book)
|
||||||
|
@ -566,7 +645,7 @@ some author you would do::
|
||||||
``can_delete=True``.
|
``can_delete=True``.
|
||||||
|
|
||||||
More than one foreign key to the same model
|
More than one foreign key to the same model
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
-------------------------------------------
|
||||||
|
|
||||||
If your model contains more than one foreign key to the same model you will
|
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
|
need to resolve the ambiguity manually using ``fk_name``. Given the following
|
||||||
|
@ -580,3 +659,27 @@ model::
|
||||||
To resolve this you can simply use ``fk_name`` to ``inlineformset_factory``::
|
To resolve this you can simply use ``fk_name`` to ``inlineformset_factory``::
|
||||||
|
|
||||||
>>> FrienshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend")
|
>>> 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.
|
||||||
|
|
Loading…
Reference in New Issue