Pregunta

Espero actualizar dinámicamente la 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, el resultado de as_p () , as_ul () , etc. no refleja la exclusión de Meta actualizada.

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

¿Es esta incluso la mejor manera de hacerlo? Supuse 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 = []
¿Fue útil?

Solución

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

La forma normal de hacerlo sería tener múltiples definiciones de clase para cada posible lista de exclusión. Pero si desea que el formulario 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 : acabo de volver a visitar esta publicación y pensé en publicar 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'))

Otros consejos

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

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)

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top