2008-11-17 12 views
22

Je souhaite mettre à jour dynamiquement la classe Meta en ligne de ModelForm à partir de ma vue. Bien que ce code semble mettre à jour la liste d'exclusion dans la classe Meta, la sortie de as_p(), as_ul(), etc. ne reflète pas la méta exclure mise à jour.Mise à jour dynamique de la classe Meta de ModelForm

Je suppose alors que le code HTML est généré lorsque ModelForm est créé pas lorsque le as_*() est appelé. Y a-t-il un moyen de forcer la mise à jour du HTML?

Est-ce encore la meilleure façon de le faire? Je viens de supposer que devrait travail.

Pensées?

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

Répondre

55

La classe Meta est utilisée pour construire dynamiquement la définition du formulaire - donc au moment où vous avez créé l'instance ModelForm, les champs ne sont pas dans l'exclude ont déjà été ajoutés comme les attributs du nouvel objet.

La méthode normale consiste simplement à avoir plusieurs définitions de classe pour chaque liste d'exclusion possible. Mais si vous voulez que le formulaire lui-même soit dynamique, vous devrez créer une définition de classe à la volée. Quelque chose comme:

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

MISE À JOUR: Je revisité ce poste et je pensais que je poste un peu plus moyen idiomatiques pour gérer une classe dynamique:

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: forme dynamique construction de classe. Malade. –

+0

Excellent. Merci! – ashchristopher

+0

grand exemple merci. possible d'avoir également le modèle défini dynamiquement? form = getModelForm (Passenger, ('field1', 'field2')) – jujule

12

Une autre façon:

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 peu plus impliqué, mais ça marchera certainement –

+8

Vous devriez probablement utiliser {} .pop() au lieu de le réglage puis la suppression. Exclude_list = kwargs.pop ('exclude_list') Enregistre une ligne de code. * hausser les épaules * –

+0

comme @JustinAbrahms a dit que j'espère que vous pouvez utiliser ** kwargs.pop ('exclude_list', default_value) ** quelque chose comme 'exclude_list = kwargs.pop ('exclude_list', '')' – suhailvs

3

Approche similaire, objectif un peu différent (ModelForm générique pour modèles arbitraires):

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

utilisation 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