2008-11-17 20 views
22

Espero actualizar dinámicamente una clase Meta en línea de ModelForm desde mi 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 metaexclusión actualizada.Actualice dinámicamente la Meta clase de ModelForm

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

¿Es esta 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 = [] 

Respuesta

55

La clase Meta se utiliza para construir dinámicamente la definición del formulario - por lo que en el momento en que haya creado la instancia ModelForm, los campos no están en el excluyen ya se han añadido como atributos del objeto nuevo.

La forma normal de hacerlo sería simplemente tener múltiples definiciones de clase para cada posible lista de exclusión. Pero si desea que el formulario en sí sea dinámico, tendrá que crear una definición de clase sobre la marcha. Algo así 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: Sólo a visitar este post y pensé que había puesto 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')) 
+2

+1: clase construcción forma dinámica. Enfermos. –

+0

Excelente. ¡Gracias! – ashchristopher

+0

buen ejemplo gracias. posible también tener el modelo establecido dinámicamente? form = getModelForm (Passenger, ('field1', 'field2')) – jujule

12

Otra forma:

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

un poco más involucrado, pero definitivamente funcionará –

+8

Probablemente deberías usar {} .pop() en lugar de configurándolo y luego eliminándolo. exclude_list = kwargs.pop ('exclude_list') Guarda una línea de código. * shrug * –

+0

como @JustinAbrahms dijo que espero que puedas usar ** kwargs.pop ('exclude_list', default_value) ** algo como 'exclude_list = kwargs.pop ('exclude_list', '')' – suhailvs

3

Enfoque similar, objetivo 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) 
2

Uso 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 
Cuestiones relacionadas