2009-07-10 5 views
2

Рассмотрим модели:Джанго - QuerySet затягивающих нулевые отношения с помощью Q

#Models 
class A(models.Model): 
    fieldOfA = models.CharField(max_length = 4) 
class B(models.Model): 
    fieldOfB = models.CharField(max_length = 4) 
class C(models.Model): 
    classA = models.ForeignKey(A, blank=True, null=True) 
    classB = models.ForeignKey(B, blank=True, null=True) 

Когда я создаю объекты C, я могу гарантировать, что объект имеет ЯВНО отношения CLASSA или ClassB.

Я ищу один набор запросов, который получает объекты C для определенных полей fieldOfA или определенных значений fieldOfB.

Я пробовал это, но он терпит неудачу (возвращает [], несмотря на наличие достоверных результатов).

#Views - assume double underscore in the query 
from django.db.models import Q 
my_query = C.objects.filter(Q(classA _ _isnull = False, classA _ _fieldOfA = 'foo') | Q(classB _ _isnull = False, classB _ _fieldOfB = 'foo')) 

Проблема, которую я вижу, это '|' это применяется. Два разных запроса для classA и classB работают нормально. В любом случае я мог бы применить один набор запросов для выполнения этой работы? Или, что еще хуже, способ слияния отдельных запросов.

ответ

2

Если вы можете быть уверены, что C либо имеет A, либо B, но и оба, ваши ограничения isnull являются излишними. Что произойдет, если вы запустите следующее?

C.objects.filter(Q(classA__fieldOfA = 'foo') | Q(classB__fieldOfB = 'foo')) 

Если это все еще не работает, запустите manage.py shell и после запуска выше запрос (гарантируя, что settings.DEBUG является True, проверьте сгенерированный SQL для выше

>>> from django.db import connection 
>>> connection.queries() 

Что вы видите?

+0

К сожалению, устранение избыточности не помогло. В SQL есть два «ЛЕВЫХ ВНЕШНИХ СОЕДИНЕНИЯ» для обоих Q (внутри которых находится INNER JOIN). Должен ли второй Q иметь ПРАВИЛЬНУЮ ВСТУПЛЕНИЕ? Значения поля B не восстанавливаются. Спасибо за помощь. Я цепляю (слияние, в некотором смысле) два запроса, которые также работают для меня. Использование этого фрагмента кода - http://www.djangosnippets.org/snippets/1103/ – tjazz

2

на самом деле, вы можете объединить QuerySet сек таким же образом, как и так:.

C.objects.filter(classA__fieldOfA='foo') | C.objects.filter(classB__fieldOfB='foo')