copying fields from model forms in django
Recently, I found myself trying to create a model form with fields spanning multiple models. I knew I could just re-define the fields manually, but that makes for poor maintainability (read: too lazy to type).
After some digging in ModelFormMetaclass
and modelform_factory()
, here's what I came up with:
from django import forms
from django.forms.models import modelform_factory
import models
# the usual deal
ChildForm = modelform_factory(models.Child)
# written in full in anticipation of custom validation, etc.
class ParentForm(forms.ModelForm):
class Meta:
model = models.Parent
# does the real magic
def copy_form_fields(src_class, dest_class):
for name, field in src_class.base_fields.iteritems():
dest_class.base_fields[name] = field
return dest_class
# alternatively, one could have overriden the meta class.
copy_form_fields(ChildForm, ParentForm)
If you're using these model forms with the admin, as most are apt to, don't forget to decorate the get_form
method - it calls modelform_factory()
to re-generate the form, so your custom, non-model fields won't get picked up.
from django.contrib import admin
class ParentAdmin(admin.ModelAdmin):
form = ParentForm
def get_form(self, *args, **kwargs):
form_class = super(ParentAdmin, self).get_form(*args, **kwargs)
return copy_form_fields(ChildForm, form_class)