Add form fields to django form dynamically
Solution 1
Assuming that p.title
is a string variable, then this should work:
if p.type_value == 1:
# Text
self.fields[p.title] = forms.CharField(label=p.human_title, required=False))
Solution 2
I recommend creating the form on the fly using type
. So, you'll need to create a function that will generate a list of all the fields you want to have in your form and then use them to generate the form, something like this :
def get_form_class():
flat_properties = FlatProperty.objects.all()
form_fields = {}
for p in flat_properties:
if p.type_value == 1:
form_fields['field_{0}'.format(p.id)] = django.forms.CharField(...)
elif p.type_value == 2:
form_fields['field_{0}'.format(p.id)] = django.forms.IntegerField(...)
else:
form_fields['field_{0}'.format(p.id)] = django.forms.BooleanField(...)
# ok now form_fields has all the fields for our form
return type('DynamicForm', (django.forms.Form,), form_fields )
Now you can use get_form_class
wherever you want to use your form, for instance
form_class = get_form_class()
form = form_class(request.GET)
if form.is_valid() # etc
For more info, you can check my post on creating dynamic forms with django: http://spapas.github.io/2013/12/24/django-dynamic-forms/
Update to address OP's comment (But then how to gain advantage of all the things ModelForm provides?): You can inherit your dynamic form from ModelForm
. Or, even better, you can create a class that is descendant of ModelForm
and defines all the required methods and attributes (like clean
, __init__
, Meta
etc). Then just inherit from that class by changing the type
call to type('DynamicForm', (CustomForm,), form_fields )
!
Related videos on Youtube
Alfonso Embid-Desmet
Updated on September 15, 2022Comments
-
Alfonso Embid-Desmet over 1 year
Due to a BD design where depending on a value, the data is stored in different cells, I have to add form fields dynamically. I was thinking on this:
class EditFlatForm(BaseModelForm): on_sale = forms.BooleanField(required=False) on_rent = forms.BooleanField(required=False) class Meta: model = Flat fields = ('title', 'flat_category', 'description') ... def __init__(self, *args, **kwargs): super(EditFlatForm, self).__init__(*args,**kwargs) flat_properties = FlatProperty.objects.all() for p in flat_properties: if p.type_value == 1: # Text setattr(self, p.title, forms.CharField(label=p.human_title, required=False)) elif p.type_value == 2: # Number setattr(self, p.title, forms.IntegerField(label=p.human_title, required=False)) else: # Boolean setattr(self, p.title, forms.BooleanField(label=p.human_title, required=False))
But the fields don't get added, what am I missing?
-
Alfonso Embid-Desmet over 9 yearsBut then how to gain advantage of all the things ModelForm provides?
-
ArtOfWarfare over 3 yearsThe dynamically created form ends up having a weird package name - if you try this
str(type('PostForm2', (Form,), {}))
- it returns<class 'django.forms.widgets.PostForm2'>
- I feel like if the form is involved in an exception and shows up in a stacktrace, that'll really confuse people...