Login

Form with Two InlineFormSets

Author:
maeck
Posted:
December 13, 2008
Language:
Python
Version:
1.0
Score:
5 (after 5 ratings)

As I was unable to find good examples to render a Form with two or more inlineformsets. Therefor I have posted this to Django snippets. This code is little different from another snippet with a Form with one InlineFormSet (the prefixes are necessary in this situation).

The example shows a person's data together with two inline formsets (phonenumbers and addresses) for a person.

You can add, update and delete from this form.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def person_view(request, person_id=None):

    if  person_id == None:
        person = Person()
    else:
        person = Person.objects.get(id = person_id)

    PhoneFormSet    = inlineformset_factory(Person, Phone, can_delete=True)
    AddressFormSet  = inlineformset_factory(Person, Address, can_delete=True)    
    
    if request.method == "POST":
        personform       = PersonForm(request.POST, instance=person)
        phoneformset    = PhoneFormSet(request.POST, request.FILES, instance=person, prefix='phone')
        addressformset  = AddressFormSet(request.POST, request.FILES, instance=person, prefix='address')
        
        if personform.is_valid() and phoneformset.is_valid() and addressformset.is_valid():
            personform.save()
            phoneformset.save()
            addressformset.save()

            if '_save' in request.POST:
                return HttpResponseRedirect('/admin/person/person/')
            if '_addanother' in request.POST:
                return HttpResponseRedirect('/admin/person/person/add/')
    else:
        personform      = PersonForm(instance=person)
        phoneformset    = PhoneFormSet(instance=person, prefix='phone')
        addressformset  = AddressFormSet(instance=person, prefix='address')

    return render_to_response('person.html', {
        'personform'        : personform,
        'phoneformset'      : phoneformset,
        'addressformset'    : addressformset,
    })


### Template for this view ###

<fieldset class="module aligned ">
{% for field in personform %}
    <div class="form-row">
            <div class="field-box">
                {{ field.errors }}
                {{ field.label_tag }}: {{ field }}
            </div>
    </div>
{% endfor %}
</fieldset>

<fieldset class="module aligned ">
<h2>Phone Numbers</h2>
<table>
     <tr>
     {% for field in phoneformset.forms.0 %}
          {% if not field.is_hidden %}
               <th>{{ field.label }}</th>
          {% endif %}
     {% endfor %}
     </tr>
     {% for f in phoneformset.management_form %}
          {{ f }}
     {% endfor %}
     {% for f in phoneformset.forms %}
          <tr>
          {% for field in f %}
               {% if not field.is_hidden %}
                    <td>
                    {{ field.errors }}
                    {{ field }}
                    </td>
               {% else %}
                    <td valign="bottom">{{ field }}</
               {% endif %}
          {% endfor %}
          </tr>
     {% endfor %}
</table>
</fieldset>

<fieldset class="module aligned ">
<h2>Addresses</h2>
<table>
     <tr>
     {% for field in addressformset.forms.0 %}
          {% if not field.is_hidden %}
               <th>{{ field.label }}</th>
          {% endif %}
     {% endfor %}
     </tr>
     {% for f in addressformset.management_form %}
          {{ f }}
     {% endfor %}
     {% for f in addressformset.forms %}
          <tr>
          {% for field in f %}
               {% if not field.is_hidden %}
                    <td>
                    {{ field.errors }}
                    {{ field }}
                    </td>
               {% else %}
                    <td valign="bottom">{{ field }}</
               {% endif %}
          {% endfor %}
          </tr>
     {% endfor %}
</table>
</fieldset>

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Tiz (on March 30, 2009):

Hello,

First, thanks a lot for this snippet, it was very usefull for me !

Then I have a comment about the case of a new person (recipe for me ^^), the "inline_model"formset.save() function need to know the id of the new person (for the foreign key) and they didn't have it. so I had to specify it manually.

Did you enconter this trouble ? and do you have a nicest solution ?

Thanks again

#

Please login first before commenting.