Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Improved the model formset and inline formset documentation to be mor…

…e 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
  • Loading branch information...
commit 6553ddc5b41e3225b61739dfd44bb63849d49ac3 1 parent 15bd649
Brian Rosner authored December 09, 2008

Showing 1 changed file with 111 additions and 8 deletions. Show diff stats Hide diff stats

  1. 119  docs/topics/forms/modelforms.txt
119  docs/topics/forms/modelforms.txt
@@ -530,7 +530,7 @@ formset to a user to edit ``Author`` model instances::
530 530
                 # do something.
531 531
         else:
532 532
             formset = AuthorFormSet()
533  
-        render_to_response("manage_authors.html", {
  533
+        return render_to_response("manage_authors.html", {
534 534
             "formset": formset,
535 535
         })
536 536
 
@@ -539,12 +539,91 @@ in a view. The only difference is that we call ``formset.save()`` to save the
539 539
 data into the database. This is described above in
540 540
 :ref:`saving-objects-in-the-formset`.
541 541
 
542  
-Using ``inlineformset_factory``
543  
--------------------------------
  542
+Using a custom queryset
  543
+~~~~~~~~~~~~~~~~~~~~~~~
  544
+
  545
+As stated earlier you can override the default queryset the model formset
  546
+uses::
  547
+
  548
+    def manage_authors(request):
  549
+        AuthorFormSet = modelformset_factory(Author)
  550
+        if request.method == "POST":
  551
+            formset = AuthorFormSet(request.POST, request.FILES,
  552
+                                    queryset=Author.objects.filter(name__startswith='O'))
  553
+            if formset.is_valid():
  554
+                formset.save()
  555
+                # do something.
  556
+        else:
  557
+            formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
  558
+        return render_to_response("manage_authors.html", {
  559
+            "formset": formset,
  560
+        })
544 561
 
545  
-The ``inlineformset_factory`` is a helper to a common usage pattern of working
546  
-with related objects through a foreign key. It takes all the same options as
547  
-a ``modelformset_factory``. Suppose you have these two models::
  562
+What is critical to point out here is that you must pass the queryset in both
  563
+the ``POST`` and ``GET`` cases shown above.
  564
+
  565
+Using the formset in the template
  566
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  567
+
  568
+There are three ways you might want to render the formset in your template.
  569
+You can let the formset do most of the work::
  570
+
  571
+    <form method="POST" action="">
  572
+        {{ formset }}
  573
+    </form>
  574
+
  575
+You can manually render the formset, but let the form deal with it self::
  576
+
  577
+    <form method="POST" action="">
  578
+        {{ formset.management_form }}
  579
+        {% for form in formset.forms %}
  580
+            {{ form }}
  581
+        {% endfor %}
  582
+    </form>
  583
+
  584
+When you manually render the forms yourself, be sure to render the management
  585
+form as shown above. Also see the :ref:`management form documentation <understanding-the-managementform>`.
  586
+
  587
+Or you can just do it all yourself::
  588
+
  589
+    <form method="POST" action="">
  590
+        {{ formset.management_form }}
  591
+        {% for form in formset.formset %}
  592
+            {% for fields in form %}
  593
+                {{ field }}
  594
+            {% endfor %}
  595
+        {% endfor %}
  596
+    </form>
  597
+
  598
+It is critical to note that if you opt to do most of the work yourself and you
  599
+don't go with a field ``{% for %}`` loop of the form, as shown in the last
  600
+example, you need to render to the primary key field. For example if you were
  601
+to render just the ``name`` and ``age`` fields of a model::
  602
+
  603
+    <form method="POST" action="">
  604
+        {{ formset.management_form }}
  605
+        {% for form in formset.formset %}
  606
+            {{ form.id }}
  607
+            <ul>
  608
+                <li>{{ form.name }}</li>
  609
+                <li>{{ form.age }}</li>
  610
+            </ul>
  611
+        {% endfor %}
  612
+    </form>
  613
+
  614
+Notice how we need to explicitly render ``{{ form.id }}``. This will ensure
  615
+the model formset, in the ``POST`` case, will work correctly. The above
  616
+example is assuming a primary key named ``id`` which is the name of the
  617
+implicit primary key Django creates for you when one isn't given. If you have
  618
+explicitly defined your own primary key field just make sure it gets rendered
  619
+(it is likely to be a visible field anyway).
  620
+
  621
+Inline Formsets
  622
+===============
  623
+
  624
+Inline formsets is a small abstraction layer on top of model formsets. It
  625
+simplifies the case of working with related objects via a foreign key. Suppose
  626
+you have these two models::
548 627
 
549 628
     class Author(models.Model):
550 629
         name = models.CharField(max_length=100)
@@ -554,7 +633,7 @@ a ``modelformset_factory``. Suppose you have these two models::
554 633
         title = models.CharField(max_length=100)
555 634
 
556 635
 If you want to create a formset that allows you to edit books belonging to
557  
-some author you would do::
  636
+some author you might do::
558 637
 
559 638
     >>> from django.forms.models import inlineformset_factory
560 639
     >>> BookFormSet = inlineformset_factory(Author, Book)
@@ -566,7 +645,7 @@ some author you would do::
566 645
     ``can_delete=True``.
567 646
 
568 647
 More than one foreign key to the same model
569  
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  648
+-------------------------------------------
570 649
 
571 650
 If your model contains more than one foreign key to the same model you will
572 651
 need to resolve the ambiguity manually using ``fk_name``. Given the following
@@ -580,3 +659,27 @@ model::
580 659
 To resolve this you can simply use ``fk_name`` to ``inlineformset_factory``::
581 660
 
582 661
     >>> FrienshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend")
  662
+
  663
+Using an inline formset in a view
  664
+---------------------------------
  665
+
  666
+You may want to provide a view that allows a user to edit the related objects
  667
+of some model. Here is how you might construct this view::
  668
+
  669
+    def manage_books(request, author_id):
  670
+        author = Author.objects.get(pk=author_id)
  671
+        BookInlineFormSet = inlineformset_factory(Author, Book)
  672
+        if request.method == "POST":
  673
+            formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
  674
+            if formset.is_valid():
  675
+                formset.save()
  676
+                # do something
  677
+        else:
  678
+            formset = BookInlineFormSet(instance=author)
  679
+        return render_to_response("manage_books.html", {
  680
+            "formset": formset,
  681
+        })
  682
+
  683
+Notice how we pass the instance in both the ``POST`` and ``GET`` cases. This
  684
+is required similiar to model formsets since the ``instance`` is simply used
  685
+to create the queryset for the model formset that lives underneath.

0 notes on commit 6553ddc

Please sign in to comment.
Something went wrong with that request. Please try again.