What I'm trying to do is create a dynamic ModelForm that generates extra fields based on one of its class-attributes to use in a ModelAdmin. Something like:
class MyModelForm(forms.ModelForm):
config_fields = ('book_type', 'is_featured', 'current_price__is_sale')
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
In this case, MyModelForm would generate fields based on the config_fields attribute by performing some introspection. My approach so far looks something like this (based on this answer https://stackoverflow.com/a/6581949/677985):
class ConfigForm(type):
def __new__(cls, name, bases, attrs):
if 'config_fields' in attrs:
for config_field in attrs['config_fields']:
# ... (removed for clarity)
attrs.update(fields)
return type(name, bases, attrs)
class MyModelForm(forms.ModelForm):
__metaclass__ = ConfigForm
config_fields = ('book_type', 'is_featured', 'current_price__is_sale')
This approach works well enough, but I'm not quite happy with it for several reasons:
- The validation doesn't seem to work, but this is a minor concern for now
- I'm not quite sure why the "if config_field in attrs:"-condition is needed, but it is
- I would prefer for MyModelForm to inherit instead of setting the __metaclass__ attribute, the base-class could then be easily reused and would allow me to easily override the clean- and __init__-methods.
I tried implementing the third item, the result being that the extra-fields did not show up in the admin-form. I'd be grateful if someone could help me figure this out, or at least point me in the right direction.
I am aware that using a metaclass for this probably overkill, and would guess that part of the problem is that ModelForm already has one or two metaclasses in its inheritance-chain. So if anyone has an alternate solution that accomplishes the same, that would make me just as happy.