2008-11-17 14 views
22

Ich hoffe, aus meiner Sicht eine Inline-Meta-Klasse von ModelForm dynamisch zu aktualisieren. Obwohl dieser Code scheint, die Ausschlussliste in der Meta-Klasse zu aktualisieren, spiegelt die Ausgabe von as_p(), as_ul() usw. die aktualisierte Meta-Ausschluss nicht wider.Dynamische Aktualisierung von ModelForms Meta-Klasse

Ich nehme dann an, dass das HTML generiert wird, wenn das ModelForm nicht erstellt wird, wenn das as_*() aufgerufen wird. Gibt es eine Möglichkeit, das Update des HTML zu erzwingen?

Ist das überhaupt der beste Weg? Ich habe gerade angenommen, dass sollte arbeiten.

Gedanken?

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

Antwort

55

Die Meta-Klasse verwendet wird, um dynamisch die Formulardefinition aufzubauen - so durch die Zeit haben Sie die Modelform-Instanz erstellt, die Felder nicht in der exclude bereits als das neue Objekt die Attribute hinzugefügt.

Der normale Weg wäre, nur mehrere Klassendefinitionen für jede mögliche Ausschlussliste zu haben. Wenn Sie jedoch möchten, dass das Formular selbst dynamisch ist, müssen Sie im Handumdrehen eine Klassendefinition erstellen. Etwas wie:

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: Ich habe diesen Beitrag revisited und dachte, ich würde ein wenig mehr idiomatischen Weg Post eine dynamische Klasse zu behandeln:

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: dynamic Formularklasse Aufbau. Krank. –

+0

Ausgezeichnet. Vielen Dank! – ashchristopher

+0

gutes Beispiel danke. möglich, um das Modell auch dynamisch zu setzen? form = getModelForm (Passagier, ('field1', 'field2')) – jujule

12

andere Art und Weise:

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

ein bisschen komplizierter, aber wird definitiv funktionieren –

+8

Sie sollten wahrscheinlich {} .pop() anstelle von verwenden Setzen Sie es und löschen Sie es dann. exclude_list = kwargs.pop ('exclude_list') Speichert eine Codezeile. * Achselzucken * –

+0

als @JustinAbrahms sagte, ich hoffe, Sie können ** kwargs.pop ('exclude_list', default_value) ** etwas wie 'exclude_list = kwargs.pop ('exclude_list', '')' – suhailvs

3

Ähnliche Ansatz, etwas anderes Ziel (generische ModelForm für beliebige Modelle):

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

Verwenden 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