views:

488

answers:

3

I am trying to automate the creation of something like this:

<input type='text' name='asdf[]' />
<input type='text' name='asdf[]' />
<input type='text' name='asdf[]' />

By cycling through a range in the form. I've been trying things like this, along with several other variations:

# in a model class
for i in range(1, prim+1):
    self.fields['asdf'] = forms.CharField(label=i)

# in the template
<form action='#' method='post'>
    {{form.as_p}}
</form>

But I haven't had any luck though.

How can I go about automating an array of inputs?

** edit ** To clarify, eventually I need to be able to access the fields in the template like this:

{% for input in form.fields.asdf %}
{{input}}
{% endfor %}

Which would then hopefully get me the original input list shown above...

+1  A: 

It should be more like e.g.:

# in a model class
for i in range(1, prim+1):
    self.fields['asdf_%s' % i] = forms.CharField(label='Label %i' % i)

But it very depends on what you want to achieve.

Felix Kling
I don't want the fields to have different names when outputted.
Brant
Is there a particular reason you don't want different field names? Just curious.
Dan Breen
@Brant: Well obviously a dictionary cannot contain more than one value for a key. In your code you are just overriding the field again and again.
Felix Kling
Yea, it was a more complex dictionary with nested lists or something inside. Either way, it didn't work.
Brant
+3  A: 

Jacob Kaplan-Moss (co-author of Django) recently posted a great article for handling dynamic forms, which should solve your problem in a preferred way: http://jacobian.org/writing/dynamic-form-generation/

He's using the same method that Felix suggests, but it's worth reading the whole article to get a better grasp on the concept.

Using the asdf[] technique is sloppy, because then you have to deal with ordering. It's also not the standard practice.

Edit:

To handle the situation where you need to detect when you hit these dynamic fields:

{% for input in form.fields %}
    {% ifequal input.label 'asdf' %}
        {{ forloop.counter }}: {{input}}<br />
    {% endifequal %}
{% endfor %}
Dan Breen
This is how I originally had things setup. Unfortunately, it doesn't quite serve my needs. There is a paragraph of description text that I need to insert before the asdf[] inputs begin... and the number of asdf[] inputs needs to be dynamic.So, I need to be able to detect that the asdf inputs are about to begin, display a paragraph, then spit them all out.
Brant
+1 Nice article you linked to.
Felix Kling
A: 

It looks like I can do what I need to do by breaking the form into multiple formsets...

http://docs.djangoproject.com/en/dev/topics/forms/formsets/#topics-forms-formsets

Then, I should be able to access each formset individually from the template, wrapping all of them into one

Brant