Making a Django form class with a dynamic number of fields
Jacob Kaplan-Moss has an extensive writeup on dynamic form fields:http://jacobian.org/writing/dynamic-form-generation/
Essentially, you add more items to the form's self.fields
dictionary during instantiation.
Here's another option: how about a formset?Since your fields are all the same, that's precisely what formsets are used for.
The django admin uses FormSet
s + a bit of javascript to add arbitrary length inlines.
class ColorForm(forms.Form): color = forms.ChoiceField(choices=(('blue', 'Blue'), ('red', 'Red')))ColorFormSet = formset_factory(ColorForm, extra=0) # we'll dynamically create the elements, no need for any formsdef myview(request): if request.method == "POST": formset = ColorFormSet(request.POST) for form in formset.forms: print "You've picked {0}".format(form.cleaned_data['color']) else: formset = ColorFormSet() return render(request, 'template', {'formset': formset}))
JavaScript
<script> $(function() { // this is on click event just to demo. // You would probably run this at page load or quantity change. $("#generate_forms").click(function() { // update total form count quantity = $("[name=quantity]").val(); $("[name=form-TOTAL_FORMS]").val(quantity); // copy the template and replace prefixes with the correct index for (i=0;i<quantity;i++) { // Note: Must use global replace here html = $("#form_template").clone().html().replace(/__prefix_/g', i); $("#forms").append(html); }; }) }) </script>
Template
<form method="post"> {{ formset.management_form }} <div style="display:none;" id="form_template"> {{ formset.empty_form.as_p }} </div><!-- stores empty form for javascript --> <div id="forms"></div><!-- where the generated forms go --> </form> <input type="text" name="quantity" value="6" /> <input type="submit" id="generate_forms" value="Generate Forms" />
you can do it like
def __init__(self, n, *args, **kwargs): super(your_form, self).__init__(*args, **kwargs) for i in range(0, n): self.fields["field_name %d" % i] = forms.CharField()
and when you create form instance, you just do
forms = your_form(n)
it's just the basic idea, you can change the code to whatever your want. :D