views:

35

answers:

2

I have a simple application where users are supposed to bet on outcome of a match. A match consists of two teams, a result and a stake. Matches with teams are created in the Django admin, and participants are to fill in result and stake.

The form must be generated dynamically, based on the matches in the database.

My idea is to have one (Django) Form instance for each match and pass these instances to the template.

It works fine when I do it from django shell, but the instances aren't rendered when I load my view.

The form looks like this:

class SuggestionForm(forms.Form):
    def __init__(self, *args, **kwargs):
        try:
            match = kwargs.pop('match')
        except KeyError:
            pass
        super(SuggestionForm, self).__init__(*args, **kwargs)
        label = match
        self.fields['result'] = forms.ChoiceField(label=label, required=True, choices=CHOICES, widget=forms.RadioSelect())
        self.fields['stake'] = forms.IntegerField(label='', required=True, max_value=50, min_value=10, initial=10)

My (preliminary) view looks like this:

def suggestion_form(request):
    matches = Match.objects.all()
    form_collection = {}

    for match in matches:
        f = SuggestionForm(request.POST or None, match=match)
        form_collection['match_%s' % match.id] = f

    return render_to_response('app/suggestion_form.html', {
        'forms': form_collection,
        },
        context_instance = RequestContext(request)
        )

My initial thought was that I could pass the form_collection to the template and the loop throught the collection like this, but id does not work:

        {% for form in forms %}
            {% for field in form %}
                {{ field }}
            {% endfor %}
        {% endfor %}

(The output is actually the dict keys with added spaces in between each letter - I've no idea why…)

It works if I only pass one Form instance to the template and only runs the inner loop.

Suggestions are greatly appreciated.

+1  A: 

To iterate over a dictionary in a django template you have to use:

{% for key,value in dictionary.items %}{{ value }}{% endfor %}

therefore

 {% for key, value in forms.items %}
    {% for field in value %}
        {{ field }}
    {% endfor %}
 {% endfor %}

should do the trick!

Otherwise you could put your forms in a list, which would make more sense if your main goal is to preserve their order and have the template code as it is!

lazerscience
Thanks, that did it! I agree that it's a better idea to put the form instances in a list instead.
vorpyg
+2  A: 

Once again, the best way to have multiple forms on a page is to use formsets.

Daniel Roseman