2010-08-07 2 views
2

J'essaie de comprendre pourquoi je ne peux pas spécifier de choix dans le widget d'un champ de formulaire si je remplace un champ ModelForm dans Django. Cela fonctionne si je donne les choix au champ mais pas au widget. Ma compréhension est/était que si vous donnez des choix à un champ, il sera passé sur le widget pour le rendu. Je sais que je peux obtenir cela pour travailler avec l'un des trois premiers extraits ci-dessous, mais je voulais juste comprendre pourquoi cette façon ne marche pas.Pourquoi la spécification de choix pour un widget ne fonctionne pas dans ModelForm .__ init__

Ceci est mon code ModelForm, merci!

from django import forms 
from models import Guest 

    class RSVPForm(forms.ModelForm): 

     class Meta: 
      model = Guest 

     def __init__(self, *args, **kwargs): 

      """ 
      Override a form's field to change the widget 
      """ 

      super(RSVPForm, self).__init__(*args, **kwargs) 

       # This works 
       self.fields['attending_ceremony'].required = True 
       self.fields['attending_ceremony'].widget=forms.RadioSelect(choices=Guest.CHOICES) 

       # This works 
       self.fields['attending_ceremony'].required = True 
       self.fields['attending_ceremony'].widget=forms.RadioSelect() 
       self.fields['attending_ceremony'].choices=Guest.CHOICES 

       # This works 
       self.fields['attending_ceremony'] = forms.TypedChoiceField(
        required=True, 
        widget=forms.RadioSelect, 
        choices=Guest.CHOICES 
       ) 

       # This doesn't - the choices aren't set (it's an empty list) 
       self.fields['attending_ceremony'] = forms.TypedChoiceField(
        required=True, 
        widget=forms.RadioSelect(choices=Guest.CHOICES) 
       ) 

Répondre

2

Je pense que la meilleure façon d'expliquer est de marcher à travers the code pour ChoiceField, la superclasse de TypeChoiceField.

class ChoiceField(Field): 
    widget = Select 
    default_error_messages = { 
     'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'), 
    } 

    def __init__(self, choices=(), required=True, widget=None, label=None, 
       initial=None, help_text=None, *args, **kwargs): 
     super(ChoiceField, self).__init__(required=required, widget=widget, label=label, 
             initial=initial, help_text=help_text, *args, **kwargs) 
     self.choices = choices 

    def _get_choices(self): 
     return self._choices 

    def _set_choices(self, value): 
     # Setting choices also sets the choices on the widget. 
     # choices can be any iterable, but we call list() on it because 
     # it will be consumed more than once. 
     self._choices = self.widget.choices = list(value) 

    choices = property(_get_choices, _set_choices) 

Avec votre exemple,

 self.fields['attending_ceremony'] = forms.TypedChoiceField(
       required=True, 
       widget=forms.RadioSelect(choices=Guest.CHOICES) 
      ) 
  1. Le widget est initialisés, avec des choix = guest.Choices
  2. super(ChoiceField, self).__init__ ensembles self.widget = un widget. Les choix du widget sont toujours définis.
  3. self.choices=choices définit les choix pour le champ et le widget à la valeur par défaut (), car il n'a pas été spécifié (voir _set_choices ci-dessus).

Espérons que cela a du sens. En regardant le code explique également pourquoi vos autres exemples fonctionnent. Soit les choix sont définis pour le widget et le champ de choix en même temps, soit les choix du widget sont définis après que le champ de choix a été initialisé.

+0

Oh oui, je suis avec vous. Il est écrasé car les choix pour le champ ne sont pas spécifiés. Merci! –

Questions connexes