Newforms, (or forms now) are without doubt one of the coolest features of Django. (Of course after Admin, Localflavor, and many others). Here is some sample code.
class EmployeeForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField()
resume = forms.FileField()
Just this code gives you
- A form which knows how to render itself as Html.
- A form which knows how to validate data on the server side.
- A form which knows how to show the relevant errors.
However think of this scenario,
You need to customise your form depending on values in the Database.
What you want to do is
class EmployeeForm(forms.Form):
name = forms.CharField()
"Show more fields depending on the Values in DB for a specific employees."
#....
#....
#....
You can do this without resorting to any black magic. Here is the code to do so,
#in models.py
type_mapping = {'CharField':forms.CharField(max_length = 100), 'TextField': forms.CharField(widget = forms.Textarea),
'BooleanField':forms.BooleanField(required = False),
'URLField': forms.URLField(), 'EmailField': forms.EmailField()
}
class EmployeeFieldModel(models.Model):
"Model for employee form fields for a specific Job board."
employee = models.ForeignKey(Employee)
name = models.CharField(max_length = 100)
type = models.CharField(max_length = 100)
order = models.IntegerField()
#in forms.py
def get_employee_form(employee):
"""Return the form for a specific Board."""
employee_fields = EmployeeFieldModel.objects.filter(employee = employee).order_by('order')
class EmployeeForm(forms.Form):
def __init__(self, *args, **kwargs):
forms.Form.__init__(self, *args, **kwargs)
self.employee = employee
def save(self):
"Do the save"
for field in employee_fields:
setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
return type('EmployeeForm', (forms.Form, ), dict(EmployeeForm.__dict__))
#in views.py
employee = Employee.objects.get(employee_slug)
get_employee_form(employee)
PS. A similar techniques works for Dynamic models.
PPS. Yes I have worked with Oracle. Yes, all my data models start with Employee and Departments.
Want to build an Web Application. Talk to Usware
Related posts:

{ 1 trackback }
{ 10 comments… read them below or add one }
Cool. Just a note, ‘dynamic form’ is a bit general, I think an accurate description of what you’re doing is generating a form for a “vertical” model.
On second thought, you’re not storing the values vertically so it really is just a dynamic form description.
Many thanks. This saved me a lot of digging through the Django source code.
Cool. Looks pretty good and interesting.
Do you think you could give a demo of what it looks like so I can see it?
You have “do the save”. Does it need an override and you just haven’t written it? What does your views.py look like if so?
Also, are the fields that are put in dynamically in the “type_mapping” variable?
Chris:
Chris: Cant give a demo, its a intranet only app.
Yes, override saving the form data to the db.
Db has
type(bad name btw, type is a builtin, mea culpa), which decides what form filed to show using type_mappingtype_mapping = {‘CharField’:forms.CharField(max_length = 100), ‘TextField’: forms.CharField(widget = forms.Textarea), ‘BooleanField’:forms.BooleanField(required = False), ‘URLField’: forms.URLField(), ‘EmailField’: forms.EmailField() }
in the drupal world there is a powerful pattern, where one app (they call module) can (1) extend the form of another app before rendering, and (2) catch the form values from the post. this might be an essential part for doing this in django. if i understand it right to do the same we just would need the form to send “before render” and “before save” signals. right?
Thanks. This was what I was looking for exactly.
I have one small addition: James Bennett suggests to use forms.BaseForm instead of forms.Form as base class for dynamically generated Form classes due to some technical reasons.
Thats a really useful trick, thanks for that! Just out of curiosity, is it necessary to use copy on the field that is looked up in type_mapping?
Yes. Django sets ordering on fields, when they are instantaited. If you do not copy, the fileds will be out of order.