0

I have a django app where I iteratively do filters in a loop. Here is a simplified example:

class Decision(models.Model):
    recommendation = models.TextField()

class Condition(models.Model):
    dec = models.ForeignKey(Decision, related_name='condition')
    temperature = models.PositiveInteger()
    pressure = models.PositiveInteger()

Decision.objects.filter(condition__temperature=22, condition__pressure=123 ).filter(condition__temperature=30, condition__pressure=144).values_list('id',flat=True)

As you can see, the conditions are ANDed. Is there a more efficient way to do this query?

Here is another approach but it is not giving me any result:

Decision.objects.filter(Q(condition__temperature=22, condition__pressure=123 ) &\
    Q(condition__temperature=30, condition__pressure=144)).values_list('id',flat=True)
max
  • 9,708
  • 15
  • 89
  • 144
  • I'm a bit surprised that the first query is apparently giving you results; I thought the filter chain is, as you state, AND-ed, and thus the first filter excludes the second (since `condition__temperature=22` excludes `condition_temperature=30`). Which is what you indeed (correctly, I think) get in your other approach. The question probably is: what are you trying to achieve, combining two exclusive conditions? –  Nov 04 '15 at 08:29
  • See also http://stackoverflow.com/questions/8164675/chaining-multiple-filter-in-django-is-this-a-bug . Filter chains are indeed OR-ed together, so to get the same behaviour in your second approach, replace & by |. If that is indeed what you want. –  Nov 04 '15 at 08:36

1 Answers1

0

You were almost correct with your query, except it must be OR:

Decision.objects.filter(
    Q(condition__temperature=22, condition__pressure=123 ) |  # OR
    Q(condition__temperature=30, condition__pressure=144)
).values_list('id',flat=True)

Obviously, your condition's temperature cannot be 22 AND 30 at the same time.

You can do the same with list of conditions:

from operator import or_
from django.db.models import Q

predicates = [
    {'condition__temperature': 22, 'condition__pressure': 123}, 
    {'condition__temperature': 30, 'condition__pressure': 144}]
conditions = [Q(x) for x in predicates]
query = Decision.objects.filter(reduce(or_, conditions))

You can read full docs about Q here: django-docs

sobolevn
  • 16,714
  • 6
  • 62
  • 60
  • There is a foreign key from Condition to Decision which means you can have 2 temperatures (in different locations). Maybe my example is not nice but the tricky part of the question is that this is a one-to-many relationship so what you've suggested would not work for me. Thanks though. – max Nov 04 '15 at 17:34