2015-11-04 6 views
0

У меня есть приложение django, где я итеративно делаю фильтры в цикле. Вот упрощенный пример:django - улучшение итерационных запросов

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) 

Как вы можете видеть, условия операции AND. Есть ли более эффективный способ сделать этот запрос?

Вот другой подход, но это не дает мне никакого результата:

Decision.objects.filter(Q(condition__temperature=22, condition__pressure=123) &\ 
    Q(condition__temperature=30, condition__pressure=144)).values_list('id',flat=True) 
+0

Я немного удивлен тем, что первый запрос, по-видимому, давая вам результаты; Я думал, что цепочка фильтров, как вы заявляете, AND-ed, и, следовательно, первый фильтр исключает второй (поскольку 'condition__temperature = 22' исключает' condition_temperature = 30'). Это то, что вы действительно (правильно, я думаю) понимаете в вашем другом подходе. Вероятно, вопрос заключается в следующем: чего вы пытаетесь достичь, объединяя два эксклюзивных условия? – Evert

+0

См. Также http://stackoverflow.com/questions/8164675/chaining-multiple-filter-in-django-is-this-a-bug. Цепочки фильтров действительно OR-ed вместе, поэтому, чтобы получить то же поведение во втором подходе, замените & на |. Если это действительно то, что вы хотите. – Evert

ответ

0

Вы были почти правильно с вашим запросом, за исключением того, что должно быть OR:

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

Очевидно, что температура вашего состояния в не может быть 22 AND 30 в то же время.

Вы можете сделать то же самое со списком условий:

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)) 

Вы можете прочитать полную документацию о Q здесь: django-docs

+0

Существует внешний ключ от условия к решению, что означает, что вы можете иметь 2 температуры (в разных местах). Может быть, мой пример не очень приятный, но сложная часть вопроса заключается в том, что это отношения «один ко многим», так что вы предложили не работать для меня. Спасибо хоть. – max