Django - Creating form for editing multiple instance of model
Question: Note: Django/Python beginner, hope this question is clear

I need to create a form where multiple instances of a model can be edited at
once in a single form, and be submitted at the same time.

For instance, I have two models, Invite and Guest, where multiple Guests can
be associated with a single Invite. I need a single form where I'm able to
edit particular details of all Guests attached to the invite, submit at the
same time, and save to the database.

I've seen a few suggestions about using [crispy-forms](http://django-crispy-
forms.readthedocs.org/en/latest/), but haven't managed to get it working.

I've created a form that provides certain inputs:

    
    
    from django import forms
    from app.models import Guest
    
    
    class ExtraForm(forms.ModelForm):
        diet = forms.CharField(max_length=128, required=False)
        transport = forms.BooleanField(initial=False)
    
        # An inline class to provide additional information on the form.
        class Meta:
            # Provide an association between the ModelForm and a model
            model = Guest
            fields = ('diet', 'transport')
    

My view consists of:

    
    
    def extra_view(request, code):
        invite = get_invite(code)
        # Get the context from the request.
        context = RequestContext(request)
    
        # Get just guests labelled as attending
        guests_attending = invite.guest_set.filter(attending=True)
    
        if request.method == 'POST':
            form = ExtraForm(request.POST)
    
            print(form.data)
    
            # Have we been provided with a valid form?
            if form.is_valid():
                # Save the new category to the database.
                # form.save(commit=True)
    
                print(form)
    
                return render(request, 'weddingapp/confirm.html', {
                    'invite': invite,
                })
            else:
                # The supplied form contained errors - just print them to the terminal for now
                print form.errors
        else:
            # # If the request was not a POST, display the form to enter details.
            GuestForm = ExtraForm()
    
        return render_to_response('weddingapp/extra.html', 
               {'GuestForm': GuestForm, 'invite': invite, 'guests_attending': guests_attending}, context)
    

And finally, my form:

    
    
    <form id="extra_form" method="post" action="{% url 'weddingapp:extra' invite.code %}">
    
        {% csrf_token %}
    
        {% for guest in guests_attending %}
            <fieldset class="form-group">
                <h3>Form for {{ guest.guest_name }}</h3>
                {% for field in GuestForm.visible_fields %}
                    {{ field.errors }}
    
                    <div>
                        {{ field.help_text }}
                        {{ field }}
                    </div>
                {% endfor %}
            </fieldset>
        {% endfor %}
    
        {{ form.management_form }}
        <table>
            {% for form in form %}
                {{ form }}
            {% endfor %}
        </table>
    
        <input type="submit" name="submit" value="Submit"/>
    </form>
    

Any advice


Answer: You need to use a `FormSet`, in particular a
[ModelFormSet](https://docs.djangoproject.com/es/1.9/topics/forms/modelforms/#django.forms.models.BaseModelFormSet):

    
    
    ...
    GuestFormSet = modelformset_factory(Guest, form=ExtraForm)
    

in your view you can use it as a normal form:

    
    
    formset = GuestFormSet(data=request.POST)
    
    if formset.is_valid():
      formset.save()
    

and in your template:

    
    
       <form method="post" action="">
         {{ formset.management_form }}
           <table>
             {% for form in formset %}
               {{ form }}
             {% endfor %}
           </table>
       </form>
    

_tip_ : you can avoid the avoid this boilerplate

    
    
    if request.method == 'POST':
        form = ExtraForm(request.POST)
    
        print(form.data)
    
        # Have we been provided with a valid form?
        if form.is_valid():
    

with a simple shortcut:

    
    
    form = ExtraForm(data=request.POST or None)
    if form.is_valid():
      ...
    

