Question

I have an html form in one of my django templates where a user can optionally select the range of an object's price and also a range of its real value price. However he is not required to.

<select name="minimum_price">
    <option value="1">1</option>
    <option value="2">2</option>
</select>

<select name="maximum_price">
    <option value="1">1</option>
    <option value="2">2</option>
</select>

<select name="min_real_value">
    <option value="1">1</option>
    <option value="2">2</option>
</select>

<select name="max_real_value">
    <option value="1">1</option>
    <option value="2">2</option>
</select>

I've read most of django's docs for that matter including the following enlightening post: Q Class. However I haven't yet figured out how to dynamically construct a query for my model given that a user may select any possible combination from these 4 select boxes.

The real problem arises when Django's __range has to be replaced with __gt or __lt when only one of the select boxes of each 'category' is selected.

This is what I've done so far:

myList = MyObjectsCost.objects.filter(price__range=(minimum_price, maximum_price),
                                   real_value__range=(min_real_value, max_real_value),
                                   **kwargs)

However this fails if one of the 4 variables is missing...

Thanks in advance.

Was it helpful?

Solution

The "clever" way Daniel Roseman is talking about, is to construct filters by strings, I assume?

It goes something like this:

method = MyObjectsCost.objects.filter
qs = method(**{'%s__%s' % (field_name, lookup_type): value})

Giving the right values for your situation you can build something like:

field_name = 'real_value'
lookup_type = 'gt'
value = 'min_real_value'

which would construct a 'real_value__gt=min_real_value' string that is passed to the filter method. So you can create filters based on strings. This can come in handy, but could also end up being ugly hacky code. So use carefully, but this concept could help you constructing your filters.

In case you like 3rd party apps look at https://github.com/alex/django-filter which gives you more flexibility with your filters too.

But never forget to keep it simple.

OTHER TIPS

You could do something clever with kwargs here, but it's probably easier if you just reflect that range is simply a combination of gt and lt anyway. So you can just build up the query dynamically:

my_list = MyObjectsCost.objects.all()
if minimum_price:
    my_list.filter(price__gt=minimum_price)
if maximum_price:
    my_list.filter(price__lt=maximum_price)
if min_real_value:
    my_list.filter(real_value__gt=min_real_value)
if max_real_value:
    my_list.filter(real_value__lt=max_real_value)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top