Dynamically Pass Model to Django ModelForm
Context
Let’s say you’d like to use Django’s powerful ModelForm
for multiple models — it goes without saying that if you’re trying to create an abstract Django application to handle multiple models within your project, you’d like to define the ModelForm
only once and not have to create custom ModelForm
’s for each of the models you’d like to support.
Concrete scenario
When I was asked to implement revert and recovery features for one of the projects I’m working on I easily decided to use the robust django-reversion extension — the thing is that it only comes with full support for Django Admin, and if you have to use it within your custom views and templates, you have to use the extension’s API directly and write your own views and templates.
Problem
If you want to use the ModelForm
, you have to define the model
property on the Meta
class, e.g.:
Solution
The solution is simple if you remember that in Python, functions can return class definitions — so, within your forms.py
you can write a form helper function:
Then, simply use the get_model_form
helper function in your view to retrieve the ModelForm
.
If you’re using Django class based views (and in this particular example I’m using FormView
), you can override the get_form_class
method and return the call to the get_model_form
function, e.g.:
Conclusion
To pass model to the ModelForm
dynamically:
- create a helper function which accepts the custom model as parameter;
- use the call to that helper function when you’re supposed to define the Django form class.