Issue
What I want to accomplish is to be able to submit multiple forms contained on one page. What I have currenlty done is supplied a view that returns 8 forms. Is it possible, within the template, to have lets say a button that will submit all of the forms contained on the page in one POST request?
Here is some code from my view:
def get_all_forms(request):
context = {}
if request.method == 'POST':
return
else:
for x in range(8):
context[x] = Form()
return render(request, 'app/all_forms.html', {'form': context})
Solution
Some issues with your code:
-
It lacks input validation.
-
You probably won’t be able to differentiate between the data submitted by the 8 instances of
Form()
, because all instances will have the same HTMLname
attribute for the<input .../>
elements.One way to make the instances distinct is to use the
prefix
keyword argument. For example:def get_all_forms(request): NUM_FORMS = 8 if request.method == 'POST': forms = [Form(request.POST, prefix=i) for i in range(NUM_FORMS)] if all((form.is_valid() for form in forms)): # Do something with the submitted data here ... return redirect('somewhere ......') else: forms = [Form(prefix=i) for i in range(NUM_FORMS)] return render(request, 'app/all_forms.html', {'forms': forms})
But a much better solution is to use formsets (see below).
Solution
Formsets allow you to have multiple copies of the same form on one page, and process all of them in one POST request. Using a formset, Django is able to handle validation for all the forms. Example:
If your form is:
from django import forms
class MyForm(forms.Form):
# ...
Create a formset that has 8 empty forms:
from django.forms import formset_factory
MyFormset = formset_factory(MyForm, extra=8) # Create 8 forms.
Then you can use the formset in your view:
from django.shortcuts import redirect, render
def get_all_forms(request):
if request.method == 'POST':
formset = MyFormset(request.POST)
if formset.is_valid(): # Validates all 8 forms.
# ... (submitted data is in formset.cleaned_data)
return redirect('somewhere ......')
else:
formset = MyFormset()
return render(request, 'app/all_forms.html', {'formset': formset})
And you can display all forms in your template using just this:
<form action="" method="post">
{% csrf_token %}
<table>
{{ formset }}
</table>
<input type="submit"/>
</form>
Further information from the documentation:
Answered By – Flux
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0