Reputation: 173
I am trying to make a form which has an option of adding multiple objects at a time. I want it to have a button "add another" - when clicked a new form field would appear for adding additional object. If there was an previous not submitted input I want the form to keep it. Is it possible to use templates tags for this(i.e. django template tags and not javascript)?
Upvotes: 1
Views: 1338
Reputation: 27523
Your form would have to be constructed based on some variables passed to it from your POST (or blindly check for attributes). The form itself is constructed every time the view is reloaded, errors or not, so the HTML needs to contain information about how many fields there are to construct the correct amount of fields for validation.
I'd look at this problem the way FormSet
s work: there is a hidden field that contains the number of forms active, and each form name is prepended with the form index. In fact, you could make a one field FormSet
.
https://docs.djangoproject.com/en/dev/topics/forms/formsets/#formsets
Here's one made from scratch - it should give you some ideas. It also answers your questions about passing arguments to __init__
- you just pass arguments to an objects constructor: MyForm('arg1', 'arg2', kwarg1='keyword arg')
### Views
class MyForm(forms.Form):
original_field = forms.CharField()
extra_field_count = forms.CharField(widget=forms.HiddenInput())
def __init__(self, *args, **kwargs):
extra_fields = kwargs.pop('extra', 0)
super(MyForm, self).__init__(*args, **kwargs)
self.fields['extra_field_count'].initial = extra_fields
for index in range(int(extra_fields)):
# generate extra fields in the number specified via extra_fields
self.fields['extra_field_{index}'.format(index=index)] = \
forms.CharField()
def myview(request):
if request.method == 'POST':
form = MyForm(request.POST, extra=request.POST.get('extra_field_count')
if form.is_valid():
print "valid!"
else:
form = MyForm()
return render(request, "template", { 'form': form })
### HTML
form_count = Number($("[name=extra_field_count]").val());
// get extra form count so we know what index to use for the next item.
$("#add-another").click(function() {
form_count ++;
element = $('<input type="text"/>');
element.attr('name', 'extra_field_' + form_count);
$("#forms").append(element);
// build element and append it to our forms container
$("[name=extra_field_count]").val(form_count);
// increment form count so our view knows to populate
// that many fields for validation
})
<form>
<div id="forms">
{{ form.as_p }}
</div>
<button id="add-another">add another</button>
<input type="submit" />
</form>
Upvotes: 1