Dynamically update ModelForm's Meta class Dynamically update ModelForm's Meta class django django

Dynamically update ModelForm's Meta class


The Meta class is used to dynamically construct the form definition - so by the time you've created the ModelForm instance, the fields not in the exclude have already been added as the new object's attributes.

The normal way to do it would be to just have multiple class definitions for each possible exclude list. But if you want the form itself to be dynamic, you'll have to create a class definition on the fly. Something like:

def get_form(exclude_list):    class MyForm(ModelForm):        class Meta:            model = Passenger            exclude = exclude_list    return MyFormform_class = get_form(('field1', 'field2'))form = form_class()

UPDATE: I just revisited this post and thought I'd post a little more idiomatic way to handle a dynamic class:

def PassengerForm(exclude_list, *args, **kwargs):    class MyPassengerForm(ModelForm):        class Meta:            model = Passenger            exclude = exclude_list        def __init__(self):            super(MyPassengerForm, self).__init__(*args, **kwargs)    return MyPassengerForm()form = PassengerForm(('field1', 'field2'))


Another way:

class PassengerInfoForm(ModelForm):    def __init__(self, *args, **kwargs):        exclude_list=kwargs.pop('exclude_list', '')        super(PassengerInfoForm, self).__init__(*args, **kwargs)        for field in exclude_list:            del self.fields[field]    class Meta:        model = Passengerform = PassengerInfoForm(exclude_list=['field1', 'field2'])


Similar approach, somewhat different goal (generic ModelForm for arbitrary models):

from django.contrib.admin.widgets import AdminDateWidgetfrom django.forms import ModelFormfrom django.db import modelsdef ModelFormFactory(some_model, *args, **kwargs):    """    Create a ModelForm for some_model    """    widdict = {}    # set some widgets for special fields    for field in some_model._meta.local_fields:        if type(field) is models.DateField:            widdict[field.name] = AdminDateWidget()    class MyModelForm(ModelForm): # I use my personal BaseModelForm as parent        class Meta:            model = some_model            widgets = widdict    return MyModelForm(*args, **kwargs)