2009-04-10 4 views
5

Diciamo che ho alcuni modelli inventati:Come modificare scelte di ModelMultipleChoiceField

class Author(Model): 
    name = CharField() 

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

E diciamo che voglio usare un ModelForm per Book:

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

semplice finora. Ma diciamo anche che ho un sacco di Autori nel mio database, e non voglio avere un campo di scelta multipla così lungo. Quindi, mi piacerebbe è quello di limitare il queryset sul campo dell'autore ModelMultipleChoiceField di BookForm. Diciamo anche che il set di query che desidero non può essere scelto fino a __init__, perché si basa su un argomento da passare.

Questo sembra che potrebbe fare il trucco:

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 

Naturalmente, se questo appena finito di lavorare io non sarei qui. Questo mi fa diventare un AttributeError. L'oggetto 'BookForm' non ha attributo 'autore'. Così, ho anche provato qualcosa di simile, dove cerco di ignorare campo di default del ModelForm e quindi impostare in un secondo momento:

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

    class Meta: 
     model = Book 

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

che produce lo stesso risultato.

Qualcuno sa come dovrebbe essere fatto?

risposta

8

oggetti Form non hanno i loro campi come attributi, è necessario guardare in attributo "campi", che è un dizionario:

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

Se si vuole comprendere appieno quello che sta succedendo qui, potrebbe essere interessato a this answer - si tratta di modelli, ma i moduli funzionano in modo simile.

7

Sebbene Carl abbia ragione sui campi, manca anche una chiamata in super classe. Questo è il modo in cui lo faccio:

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

Sì, la mia vera area problematica ha la chiamata di super classe, ma l'ho saltata per questo esempio. – Brian

+0

Abbastanza giusto. Lascerò tutto questo a chiunque vada in questa domanda per amor di riferimento, immagino. –

+1

Definitivamente. È importante vedere che il super() .__ init __() deve accadere prima dell'accesso ai campi. – Brian