field choices() as queryset?

robos85 picture robos85 · Feb 24, 2011 · Viewed 25.1k times · Source

I need to make a form, which have 1 select and 1 text input. Select must be taken from database. model looks like this:

class Province(models.Model):
    name = models.CharField(max_length=30)
    slug = models.SlugField(max_length=30)

    def __unicode__(self):
        return self.name

It's rows to this are added only by admin, but all users can see it in forms. I want to make a ModelForm from that. I made something like this:

class ProvinceForm(ModelForm):
    class Meta:
        CHOICES = Province.objects.all()

        model = Province
        fields = ('name',)
        widgets = {
            'name': Select(choices=CHOICES),
        }

but it doesn't work. The select tag is not displayed in html. What did I wrong?

UPDATE:

This solution works as I wanto it to work:

class ProvinceForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(ProvinceForm, self).__init__(*args, **kwargs)
        user_provinces = UserProvince.objects.select_related().filter(user__exact=self.instance.id).values_list('province')
        self.fields['name'].queryset = Province.objects.exclude(id__in=user_provinces).only('id', 'name')

    name = forms.ModelChoiceField(queryset=None, empty_label=None)

    class Meta:
        model = Province
        fields = ('name',)

Answer

Yuji 'Tomita' Tomita picture Yuji 'Tomita' Tomita · Feb 24, 2011

Read Maersu's answer for the method that just "works".

If you want to customize, know that choices takes a list of tuples, ie (('val','display_val'), (...), ...)

Choices doc:

An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field.

from django.forms.widgets import Select


class ProvinceForm(ModelForm):
    class Meta:
        CHOICES = Province.objects.all()

        model = Province
        fields = ('name',)
        widgets = {
            'name': Select(choices=( (x.id, x.name) for x in CHOICES )),
        }