2009-04-10 8 views
5

Disons que j'ai quelques modèles contrived:Comment modifier les choix de ModelMultipleChoiceField

class Author(Model): 
    name = CharField() 

class Book(Model): 
    title = CharField() 
    author = ForeignKey(Author) 

Et disons que je veux utiliser un ModelForm pour livre:

class BookForm(ModelForm): 
     class Meta: 
     model = Book 

simple jusqu'à présent. Mais disons aussi que j'ai une tonne d'Auteurs dans ma base de données, et je ne veux pas avoir un champ de choix multiple aussi long. Donc, je voudrais est de restreindre le jeu de requête sur le champ auteur ModelMultipleChoiceField du BookForm. Disons aussi que le queryset que je veux ne peut pas être choisi avant __init__, car il dépend d'un argument à passer.

Cela semble que cela pourrait faire l'affaire:

class BookForm(ModelForm): 
    class Meta: 
     model = Book 

    def __init__(self, letter): 
     # returns the queryset based on the letter 
     choices = getChoices(letter) 
     self.author.queryset = choices 

Bien sûr, si cela fonctionne simplement je ne serais pas ici. Cela me donne une AttributeError. L'objet 'BookForm' n'a pas d'attribut 'author'. Donc, j'ai aussi essayé quelque chose comme ça, où je tente de remplacer le champ par défaut de ModelForm puis régler plus tard:

class BookForm(ModelForm): 
    author = ModelMultipleChoiceField(queryset=Author.objects.all()) 

    class Meta: 
     model = Book 

    def __init__(self, letter): 
     choices = getChoices(letter) 
     self.author.queryset = choices 

qui produit le même résultat.

Quelqu'un sait-il comment cela doit être fait?

Répondre

8

objets de formulaire ne sont pas leurs champs comme des attributs, vous devez regarder dans l'attribut « champs », qui est un dictionnaire:

self.fields['author'].queryset = choices 

Si vous voulez comprendre ce qui se passe ici, vous pourrait être intéressé par this answer - il s'agit de modèles, mais les formulaires fonctionnent de manière similaire.

7

Bien que Carl ait raison sur les champs, il vous manque également un appel de super classe. Voici comment je le fais:

class BookForm(ModelForm): 
    author = ModelMultipleChoiceField(queryset=Author.objects.all()) 

    class Meta: 
     model = Book 

    def __init__(self, *args, **kwargs): 
     letter = kwargs.pop('letter') 
     super(BookForm, self).__init__(*args, **kwargs) 
     choices = getChoices(letter) 
     self.fields['author'].queryset = choices 
+0

Oui, mon problème réel a l'appel de super classe, mais je l'ai ignoré pour cet exemple. – Brian

+0

Assez juste. Je vais laisser cela en suspens à quiconque se promène dans cette question pour référence, je suppose. –

+1

Certainement. Il est important de voir que le super() .__ init __() doit arriver avant l'accès aux champs. – Brian

Questions connexes