2009-04-10 12 views
5

Digamos que tengo algunos modelos artificiales:Cómo modificar opciones de ModelMultipleChoiceField

class Author(Model): 
    name = CharField() 

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

Y digamos que quiero usar un ModelForm de libro:

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

simple hasta el momento. Pero también digamos que tengo un montón de Autores en mi base de datos, y no quiero tener un campo de selección múltiple tan largo. Entonces, me gustaría restringir el queryset en el campo de autor ModelFieldMultipleChoiceField de BookForm. Digamos también que el conjunto de interrogación que deseo no se puede elegir hasta __init__, ya que depende de un argumento para pasar.

Esto parece que podría hacer el truco:

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 

Por supuesto, si eso sólo funcionó yo no estaría aquí. Eso me da un AttributeError. El objeto 'BookForm' no tiene ningún atributo 'autor'. Por lo tanto, también probé algo como esto, donde intento de anular campo predeterminado de la ModelForm y luego configurarlo más tarde:

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

    class Meta: 
     model = Book 

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

que produce el mismo resultado.

¿Alguien sabe cómo se debe hacer esto?

Respuesta

8

objetos Form no tienen sus campos como atributos, que necesitan especial atención en el atributo "campos", que es un diccionario:

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

Si se quiere entender completamente lo que está pasando aquí, podría estar interesado en this answer - se trata de Modelos, pero los Formularios funcionan de manera similar.

7

Aunque Carl tiene razón sobre los campos, también se está perdiendo una llamada de superclase. Así es como lo hago:

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í, mi área de problema real tiene la llamada de superclase, pero me salté este ejemplo. – Brian

+0

Bastante justo. Dejaré esto para cualquiera que deambule en esta pregunta por referencia, supongo. –

+1

Definitivamente. Es importante ver que el super() .__ init __() debe ocurrir antes del acceso a los campos. – Brian

Cuestiones relacionadas