Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically update ModelForm's Meta class

I am hoping to dynamically update a ModelForm's inline Meta class from my view. Although this code seems to update the exclude list in the Meta class, the output from as_p(), as_ul(), etc does not reflect the updated Meta exclude.

I assume then that the html is generated when the ModelForm is created not when the as_*() is called. Is there a way to force the update of the HTML?

Is this even the best way to do it? I just assumed this should work.

Thoughts?

from django.forms import ModelForm

from testprogram.online_bookings.models import Passenger

class PassengerInfoForm(ModelForm):

    def set_form_excludes(self, exclude_list):
        self.Meta.exclude = excludes_list

    class Meta:
        model = Passenger
        exclude = []
like image 477
ashchristopher Avatar asked Nov 17 '08 23:11

ashchristopher


2 Answers

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 MyForm

form_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'))
like image 198
Daniel Naab Avatar answered Oct 22 '22 21:10

Daniel Naab


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 = Passenger

form = PassengerInfoForm(exclude_list=['field1', 'field2'])
like image 36
user85461 Avatar answered Oct 22 '22 21:10

user85461