views:

65

answers:

3

I have a form along the lines of:

class aForm(forms.Form):
  input1 = forms.CharField()
  input2 = forms.CharField()
  input3 = forms.CharField()

What I'm hoping to do is add an additional input3 to the form when the user clicks an "add another input3".

I've read a bunch of ways that let me add new forms using formsets, but I don't want to append a new form, I want to just add a new input3.

Is this possible?

+2  A: 

I would define input3 in your form definition, not require it, and then hide it by default. The user can then show the input using JavaScript.

If you want to allow the user to add an undefined amount of additional inputs, I would look further into formsets.

Zach
A: 

Perhaps something like this:

from django import forms
from django.utils.datastructures import SortedDict
def some_view(request):
    data = {}

    # Using session to remember the row count for simplicity
    if not request.session.get('form_rows', None):
        request.session['form_rows'] = 3

    # If posted with add row button add one more row
    if request.method == 'POST' and request.POST.get('rows', None):
            request.session['form_rows'] += 1
            data = request.POST

    # Create appropriate number of form fields on the fly
    fields = SortedDict()
    for row in xrange(1, request.session['form_rows']):
        fields['value_{0}'.format(row)] = forms.IntegerField()

    # Create form class
    MyForm = type('MyForm', (forms.BaseForm,), { 'base_fields': fields })

    form = MyForm(initial=data)

    # When submitted...
    if request.method == 'POST' and not request.POST.get('rows', None):
        form = MyForm(request.POST)
        if form.is_valid():
            # do something
    return render_to_response('some_template.html', {
        'form':form,
    }, context_instance=RequestContext(request))

With template:

<form action="" method="post">
    {{ form }}
    <input type="submit" />
    <input type="submit" value='Add' name='rows' />
</form>

This is over simplified but it works.

You could easily modify this example so you can make request using AJAX and just replace old form with new one.

rebus
+2  A: 

for adding dynamic fields overwrite the init method.

Something like this:

class aForm(forms.Form):
  input1 = forms.CharField()
  input2 = forms.CharField()

  def __init__(self, addfields=0, *args, **kwargs):
    super(aForm, self).__init__(*args, **kwargs)

    #add new fields
    for i in range(3,addfields+3)
       self.fields['input%d' % i] = forms.CharField()
maersu