| 1 | = Creating Fields with Dynamic Forms = |
| 2 | |
| 3 | Imagine you're creating a Django app to deal with, oh, user polls or something silly like that. You could create a form that includes a place for the pollee to enter his/her name, age, and to answer a question. |
| 4 | {{{ |
| 5 | import django.newforms as forms |
| 6 | |
| 7 | class Survey(forms.Form): |
| 8 | name = forms.CharField(max_length=20) |
| 9 | age = forms.IntegerField() |
| 10 | answer = forms.ChoiceField(choices=(('0', 'Not at All'), |
| 11 | ('1', 'Sometimes'), |
| 12 | ('2', 'Often'), |
| 13 | ('3', 'Always'))) |
| 14 | }}} |
| 15 | When you display this, you'll get a nice form with three places to input information. |
| 16 | |
| 17 | But what if you're allowing your users to create their own survey questions, so that you don't know ahead of time how many answers you'll need? Luckily, you can add fields to the form as you're constructing it, in addition to specifying them as class attributes. If you have all your survey questions in a list (let's call it `questions` just to be confusing), you could create a `Survey` class that looks like this: |
| 18 | {{{ |
| 19 | class Survey(forms.Form): |
| 20 | name = forms.CharField(max_length=20) |
| 21 | age = forms.IntegerField() |
| 22 | |
| 23 | def __init__(questions, *args, **kwargs): |
| 24 | super(Survey, self).__init__(*args, **kwargs) |
| 25 | # now we add each question individually |
| 26 | for i in range(len(questions)): |
| 27 | self.fields['question_%d' % i] = forms.ChoiceField(label=questions[i], ...) |
| 28 | }}} |
| 29 | |
| 30 | When you display this form, you'll get separate spot to answer each of the questions you passed in, each with its own index so that you can match it to the question. One complication--if you choose to use this method, you have to pass the same `questions` list each time you create the form, both on the GET when it's empty and on the POST when it has your answers. It is possible to avoid this, but it takes a little more thought when you set up your views and the workflow. (Saving stuff in the session can make things much easier.) |
| 31 | |
| 32 | This technique isn't limited to defining new fields. You can also set a field's `initial` value in the `__init__` method, which is really helpful when your forms depend on your models, but don't match up exactly so you can't use the `ModelForm` framework. |