Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a conditional query in Django?

I am trying to filter by a calculated field, where the calculation depends on the value of other fields.

I'm trying to filter by sales_price (the calculated field), where sales_price is defined like below pseudocode

if discount is NULL                                                             
    sales_price = price                                                         
else                                                                            
    sales_price = price - price*discount/100 

The end goal is to filter sales_price by range:

filter(sales_price__range=(price_min, price_max))                                   

Here is my model:

class Product(models.Model):                                                
  price = models.IntegerField()                                             
  discount = models.IntegerField(blank=True, null=True)                                                                             
like image 554
asing177 Avatar asked Feb 27 '16 10:02

asing177


People also ask

Does Django ORM support subquery?

¶ Django allows using SQL subqueries.

What does .all do in Django?

Definition of the all() manager method: all() Returns a copy of the current QuerySet (or QuerySet subclass). This can be useful in situations where you might want to pass in either a model manager or a QuerySet and do further filtering on the result.

What is a QuerySet in Django?

A QuerySet is a collection of data from a database. A QuerySet is built up as a list of objects. QuerySets makes it easier to get the data you actually need, by allowing you to filter and order the data.


1 Answers

I'll just point you in the right direction:

Use F expressions in a conditional expression with When and Case

You want to sort by a value that depends on other values, so let's use a F Expression (because sales_price depends on other fields) in a conditional expression (because the final expression depends on whether discount is NULL or not)

First we construct a sales_price value that depends on discount and price, and annotate our query with it:

from django.db.models import When, Case, F, IntegerField

Product.objects.annotate(
     sales_price=Case(
         When(discount__isnull=True, then=F('price')),
         When(discount__isnull=False, then=(F('price') - (F('discount') * F('price')) / 100)),
         output_field=IntegerField(),
     )
)

Now with this, you have included a sales_price that you can filter with:

   Product.objects.annotate(...).filter(sales_price__range=(price_min, price_max)
like image 107
bakkal Avatar answered Oct 26 '22 17:10

bakkal