Django - How ModelChoiceField queryset's works?

Adrian Lopez picture Adrian Lopez · Mar 24, 2013 · Viewed 16.9k times · Source

I have a form with a ModelChoiceField, and i want to load on it a table from my DB. If i use this queryset on my form's init, then my view's form.is_valid works fine:

self.fields['categoria_formfield'].queryset = sitio_categoria.objects.exclude(categoria='patrimonio').values_list('idCategoria',flat=True)

enter image description here

That code show a id's list on the ModelChoiceField, but what i need it's to show the categories list. So i use:

self.fields['categoria_formfield'].queryset = sitio_categoria.objects.exclude(categoria='patrimonio').values_list('categoria',flat=True)

But using this code .is_valid don't validate and i recive a form error: "Select a valid choice. That choice is not one of the avaliable choices." Some clue about what could be the problem?

Error recived

MODEL

class sitio_categoria(models.Model):
    idCategoria         =   models.AutoField(primary_key=True)
    categoria           =   models.CharField(max_length=30, null=False, unique=True)

FORM

class anadirComercioPaso1_form(forms.Form):
        categoria_formfield = forms.ModelChoiceField(widget=forms.Select(attrs={'size':'13', 'onchange':'this.form.action=this.form.submit()'}), queryset=sitio_categoria.objects.none())

def __init__(self, *args, **kwargs):
        super(anadirComercioPaso1_form, self).__init__(*args,**kwargs)
        self.fields['categoria_formfield'].queryset = sitio_categoria.objects.exclude(categoria='patrimonio').values_list('categoria',flat=True)

Answer

Pavel Anossov picture Pavel Anossov · Mar 24, 2013

Do not use values_list, (or values), ModelChoiceField needs actual model objects.

queryset = sitio_categoria.objects.exclude(categoria='patrimonio')

 

ModelChoiceField will use the primary keys of the objects for validation and their unicode representation for displaying. So you will need to define the conversion to unicode in your model:

class sitio_categoria(models.Model):
    idCategoria = models.AutoField(primary_key=True)
    categoria = models.CharField(max_length=30, null=False, unique=True)

    def __unicode__(self):
        return self.categoria

 

ModelChoiceField documentation

The __unicode__ method of the model will be called to generate string representations of the objects for use in the field’s choices;