Actualizar dinámicamente la clase Meta de ModelForm

Espero actualizar dinámicamente una clase Meta en línea de ModelForm desde mi punto de vista. Aunque este código parece actualizar la lista de exclusión en la clase Meta, la salida de as_p() , as_ul() , etc. no refleja la Meta exclude actualizada.

Asumo entonces que el html se genera cuando el ModelForm no se crea cuando se llama as_*() . ¿Hay alguna forma de forzar la actualización del HTML?

¿Es esta incluso la mejor manera de hacerlo? Simplemente asumí que esto debería funcionar.

¿Pensamientos?

 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 = [] 

Related of "Actualizar dinámicamente la clase Meta de ModelForm"

La clase Meta se usa para construir dinámicamente la definición del formulario, por lo que, cuando haya creado la instancia de ModelForm, los campos que no están en la exclusión ya se agregaron como atributos del nuevo objeto.

La forma normal de hacerlo sería tener solo múltiples definiciones de clase para cada posible lista de exclusión. Pero si desea que el formulario sea dynamic, tendrá que crear una definición de clase sobre la marcha. Algo como:

 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() 

ACTUALIZACIÓN : acabo de revisar esta publicación y pensé que publicaría una forma un poco más idiomática para manejar una clase dinámica:

 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')) 

De otra manera:

 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']) 

Enfoque similar, objective algo diferente (ModelForm genérico para modelos arbitrarios):

 from django.contrib.admin.widgets import AdminDateWidget from django.forms import ModelForm from django.db import models def 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) 

Utilice modelform_factory ( doc ):

 from django.forms.models import modelform_factory from testprogram.online_bookings.models import Passenger exclude = ('field1', 'field2') CustomForm = modelform_factory(model=Passenger, exclude=exclude) # generates ModelForm dynamically custom_form = CustomForm(data=request.POST, ...) # form instance