Ok, dynamic fields. Now we're digging into the dark depths of Django. Not something you can find in the documentation, well me anyway.
There are a few posts online about it but some are fairly old, before the Django "newforms" were introduced. All that means is if you tried that code it won't work.
This example shows us how to:
- Pass an argument to the form upon creation (user variable)
- Dynamically create fields upon creation
- Modify the choices for an existing field upon creation
These should cover the use cases of most dynamic forms.
01.
class
ExampleDynamicForm(forms.Form):
02.
normal_field
=
forms.CharField()
03.
choice_field
=
forms.CharField(widget
=
forms.Select(choices
=
[ (
'a'
,
'A'
), (
'b'
,
'B'
), (
'c'
,
'C'
) ]))
04.
05.
def
__init__(
self
, user,
*
args,
*
*
kwargs):
06.
# This should be done before any references to self.fields
07.
super(ExampleDynamicForm,
self
).__init__(
*
args,
*
*
kwargs)
08.
09.
self
.user
=
user
10.
self
.id_list
=
[]
11.
12.
# Some generic loop condition to create the fields
13.
for
blah
in
Blah.objects.for_user(user
=
self
.user):
14.
self
.id_list.append(blah.id)
15.
16.
# Create and add the field to the form
17.
field
=
forms.ChoiceField(label
=
blah.title, widget
=
forms.widgets.RadioSelect(), choices
=
[(
'accept'
,
'Accept'
), (
'decline'
,
'Decline'
)])
18.
self
.fields[
"blah_%s"
%
blah.id]
=
field
19.
20.
# Change the field options
21.
self
.fields[
'choice_field'
].widget.choices
=
[ (
'd'
,
'D'
), (
'e'
,
'E'
), (
'f'
,
'F'
) ]
To use the form:
1.
form
=
ExampleDynamicForm(request.user)
It may look scary but it's not that bad.
Follow the formula and you'll be fine.
Note: Remember, the super().__init__() call should be made early on before any references to self.fields.