In James Bennett’s article “So you want a dynamic form” (Nov. 9, 2008), he wrote that to create a dynamic form you can do something like this:
def make_contact_form(user):
fields = { 'name': forms.CharField(max_length=50),
'email': forms.EmailField(),
'message': forms.CharField(widget=forms.Textarea) }
if not user.is_authenticated():
fields['captcha'] = CaptchaField()
return type('ContactForm', (forms.BaseForm,), { 'base_fields': fields })
But how would you do the same thing with forms.ModelForm?
So far I’m just doing something like this (I couldn’t figure out how to use type with an inner class ‘Meta’)
def make_order_edit_form(include_fields):
class _OrderEditForm(forms.ModelForm):
if 'fa_date' in include_fields:
fa_date = CustomDateTimeField(label="first appointment time")
class Meta:
model = Order
fields = include_fields
widgets = custom_widgets
return _OrderEditForm
where include_fields is a tuple of fields I want to show.
However even if I wrote a correct make_order_edit_form, how do I use it in views.py? Specifically how do I pass both the POST request and the order instance to it? Normally I would do something like
order = Order.objects.get(pk=pk)
order_form = OrderEditForm(data=request.POST, instance=order)
Bonus question:
Why did Bennett create a ContactForm out of forms.BaseForm instead of forms.Form? (I’m assuming that’s why the fields are called base_fields as well.)
make_order_edit_formreturns aModelFormclass, thus you couldFor the bonus question, check the
Formcode:The
Formhas a customized meta classDeclarativeFieldsMetaclasswhich automatically collects form fields written in declarative syntax, if you useFormintype(), it looks like (take Bennett’s example)update
to build up
ModelFormusingtype, no much different