Populate choice field from model with conditional query Django

Hi, is it possible to populate a choice field with data from a model with a conditional query? The choices will update depending on the data so I’d like it somewhat dynamic.

See example:

FRUIT = (
( select fruit from basket where id = 'x' and price = '1'; : select fruit from basket where id = 'x' and price = '1'; ),
( select fruit from basket .... ;: select fruit from basket .... ;),
)

class SubmitChoiceForm(forms.ModelForm):
    preference = forms.ChoiceField(choices=FRUIT, required=False, label= '')

class Meta:
    model = user_choice
    fields = (
        'preference',
    )

Does Django support this?
Thanks

The short answer is yes, Django supports this. The slightly longer answer is that the specific solution somewhat depends upon the precise context for which a solution is being found.

For the simplest case, refer to the ChoiceField documentation. The choices parameter is either a list of 2-tuples or a callable. (emphasis mine)

This callable can be a function that returns the list of 2-tuples as the choices, and can contain a query that selects the options from a table.

Any more detailed answer is going to need a lot more context about what exactly you’re trying to do, and what you mean by ‘dynamic’. (This query would be evaluated when the form is built. If the underlying table is changed while the user is looking at the form, the form will not be updated.)

Ken

Hi @KenWhitesell ,

As in ‘somewhat dynamic’ I mean to be able to call the ‘choices’ from the database with query. Since posting, I just built a class that was able to return a set of tuples (see below):

CLASS:

import psycopg2

class get_fruits:
def __init__(self, id, fruit_price):
    self.id = id
    self.fruit_price = fruit_price

def show_fruit(self):
    try:
        id = self.id
        fruit_price = self.fruit_price
        dbase = 'dbase'
        dbuser = 'user'
        conn = psycopg2.connect("host=localhost dbname=" + dbase + " user=" + dbuser)
        cur = conn.cursor()
        postgreSQL_select_Query = """select fruit, fruit from basket
                                     where id = '""" + id + "' and fruit_price = '" + fruit_price + "';"
        cur.execute(postgreSQL_select_Query)
        fruit = cur.fetchall()
        return fruit[0]
    except (Exception, psycopg2.Error) as error:
        print("Error while fetching data from PostgreSQL", error)

Back to example:

FRUIT = (
( get_fruits('1201', 3.50).show_fruit()),
( get_fruits('1201', 6.25).show_fruit()),
)
print(FRUIT) 
(('Orange', 'Orange'), ('Apple', 'Apple'))

class SubmitChoiceForm(forms.ModelForm):
preference = forms.ChoiceField(choices=FRUIT, required=False, label= '')

class Meta:
model = user_choice
fields = (
    'preference',
)

This works fine but I would like to use less SQL queries and rather built in Django functions. I was hoping for something like:

basket.objects.filter(id= '1202', fruit_price= 3.50)

> ('Orange')

Cheers,

The “what you were hoping for” is the right approach, you just want it returned as 2-tuple and not as a basket object.

What you’re more looking for is the values_list function:

basket.objects.filter(id='1202', fruit_price=3.50).values_list('id', 'fruit')

Note: You’re going to find it a lot less confusing now and down the road if you start adapting the standard Python and Django coding patterns. Particularly, you should name your classes (and therefore your models) with a Capitalized name. (It took me a while to realize that “basket” was a model and not a variable.)

Ken

That is exactly what I needed.

Thanks for the help!