Domanda

Spero di aggiornare dinamicamente una classe Meta inline di ModelForm dal mio punto di vista. Sebbene questo codice sembri aggiornare l'elenco di esclusione nella classe Meta, l'output di as_p () , as_ul () , ecc. Non riflette la Meta exclude aggiornata.

Suppongo quindi che l'html sia generato quando ModelForm non viene creato quando viene chiamato as _ * () . C'è un modo per forzare l'aggiornamento dell'HTML?

È anche questo il modo migliore per farlo? Ho appena pensato che questo dovrebbe funzionare.

Pensieri?

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 = []
È stato utile?

Soluzione

La classe Meta viene utilizzata per costruire dinamicamente la definizione del modulo, quindi al momento della creazione dell'istanza ModelForm, i campi non inclusi nell'esclusione sono già stati aggiunti come attributi del nuovo oggetto.

Il modo normale per farlo sarebbe quello di avere solo più definizioni di classe per ogni possibile elenco di esclusione. Ma se vuoi che il modulo stesso sia dinamico, dovrai creare al volo una definizione di classe. Qualcosa del tipo:

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

AGGIORNAMENTO : ho appena rivisto questo post e ho pensato di pubblicare un modo un po 'più idiomatico per gestire una classe dinamica:

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

Altri suggerimenti

Un altro modo:

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

Approccio simile, obiettivo in qualche modo diverso (ModelForm generico per modelli arbitrari):

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)

Usa 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top