2017-10-13 2 views
1

je créé un formulaire avec plusieurs champs dynamiques (sans attributs de classe) qui sont ajoutés à self.fields dans la fonction __init__ comme ceci:Django: forme de charge avec des champs dynamiques

class CustomForm(django.forms.Form): 
    def __init__(dynamic_fields, *args, **kwargs): 
     super(CustomForm, self).__init__(*args, **kwargs) 
     for name, field in dynamic_fields.items(): 
      self.fields[name] = field 

dynamic_fields = {'val1': IntegerField(), 'val2': FloatField()} 
CustomForm(dynamic_fields) 

Maintenant, je ne sais pas comment pour charger le formulaire après une demande POST. Normalement, je ferais quelque chose comme:

custom_form = CustomForm(request.POST) 
if custom_form.is_valid(): 
    data = custom_form.cleaned_data 
    ... 

Mais comme les champs ne sont pas connus pour former quand super est appelé, je ne sais pas comment charger les champs manuellement par la suite. Des idées?

+0

Les champs sont-ils toujours pointés sur le même type de champ? – grrrrrr

+0

non, les types de champs peuvent être de tous les types de champs django valides – Henhuy

Répondre

1

Vous pouvez mettre à jour base_fields avant d'appeler le super__init__:

class CustomForm(django.forms.Form): 
    def __init__(dynamic_fields, *args, **kwargs): 
     self.base_fields.update(dynamic_fields) 
     super(CustomForm, self).__init__(*args, **kwargs) 

dynamic_fields = {'val1': IntegerField(), 'val2': FloatField()} 
CustomForm(dynamic_fields) 
+0

Cela a fait l'affaire! Après avoir appelé 'custom = CustomForm (dynamic_fields, request.POST)' je peux continuer à appeler 'custom.is_valid()' et obtenir des données via 'custum.cleaned_data'. Merci! – Henhuy

+0

Nous venons de découvrir que votre solution ne fonctionne pas si vous utilisez plusieurs 'CustomForms' sur une seule page. C'est parce que 'base_fields' est un attribut de classe. Ainsi, en le changeant change les champs pour ** all ** 'CustomForms', menant aux copies de champ dans chaque forme. – Henhuy

+0

Certes, la solution est assez hacky. Mais je pense que c'est dans la nature de ce que vous essayez de faire. Dans le '__init__ 'de' BaseForm' l'attribut 'fields' est créé en copiant' self.base_fields'. Donc je suppose que faire une copie de 'self.base_fields' dans' init 'de 'CustomForm' avant l'appel de' update' et le réinitialiser après avoir appelé 'super's' init' devrait faire l'affaire – lmr2391

0

Pour moi, il a travaillé à l'attribut de données vient de mettre de Form classe, semblable à __init__ fonction de la classe Form. En outre, l'attribut is_bound doit être configuré pour valider le formulaire via is_valid() méthode:

class CustomForm(django.forms.Form): 
    def __init__(dynamic_fields, data=None, *args, **kwargs): 
     super(CustomForm, self).__init__(*args, **kwargs) 
     for name, field in dynamic_fields.items(): 
      self.fields[name] = field 
     self.is_bound = data is not None 
     self.data = data or {} 

Mais je ne suis pas tout à fait sûr, si cela est solution correcte ?!