field choices() as queryset? field choices() as queryset? django django

field choices() as queryset?


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 Selectclass ProvinceForm(ModelForm):    class Meta:        CHOICES = Province.objects.all()        model = Province        fields = ('name',)        widgets = {            'name': Select(choices=( (x.id, x.name) for x in CHOICES )),        }


ModelForm covers all your needs (Also check the Conversion List)

Model:

class UserProvince(models.Model):    user = models.ForeignKey(User)    province = models.ForeignKey(Province)

Form:

class ProvinceForm(ModelForm):    class Meta:        model = UserProvince        fields = ('province',)

View:

   if request.POST:        form = ProvinceForm(request.POST)        if form.is_valid():            obj = form.save(commit=True)            obj.user = request.user            obj.save()   else:        form = ProvinceForm() 


If you need to use a query for your choices then you'll need to overwrite the __init__ method of your form.

Your first guess would probably be to save it as a variable before your list of fields but you shouldn't do that since you want your queries to be updated every time the form is accessed. You see, once you run the server the choices are generated and won't change until your next server restart. This means your query will be executed only once and forever hold your peace.

# Don't do thisclass MyForm(forms.Form):    # Making the query    MYQUERY = User.objects.values_list('id', 'last_name')    myfield = forms.ChoiceField(choices=(*MYQUERY,))    class Meta:        fields = ('myfield',)

The solution here is to make use of the __init__ method which is called on every form load. This way the result of your query will always be updated.

# Do this insteadclass MyForm(forms.Form):    class Meta:        fields = ('myfield',)    def __init__(self, *args, **kwargs):        super().__init__(*args, **kwargs)        # Make the query here        MYQUERY = User.objects.values_list('id', 'last_name')        self.fields['myfield'] = forms.ChoiceField(choices=(*MYQUERY,))

Querying your database can be heavy if you have a lot of users so in the future I suggest some caching might be useful.