我的查询需要使用ID
精确过滤2位作者理论上,
Book.objects.filter(author__id=1, author__id=2).
这是不可能的。
我该如何解决这个问题?
干杯, 米奇
答案 0 :(得分:36)
起初并不直观,但答案就在我们面前。
Book.objects.filter(author__id=1).filter(author__id=2)
如果您想要完全匹配,则可能会进一步过滤那些只有2位作者的项目。
Book.objects.annotate(count=Count('author')).filter(author__id=1)\
.filter(author__id=13).filter(count=2)
如果你想动态完全匹配,那么这个怎么样?:
def get_exact_match(model_class, m2m_field, ids):
query = model_class.objects.annotate(count=Count(m2m_field))\
.filter(count=len(ids))
for _id in ids:
query = query.filter(**{m2m_field: _id})
return query
matches = get_exact_match(MyModel, 'my_m2m_field', [1, 2, 3, 4])
# matches is still an unevaluated queryset, so you could run more filters
# without hitting the database.
答案 1 :(得分:0)
新问题指向这个重复题,所以这里是更新的答案(针对一个特定的后端)。
如果后端是Postgres,则所需的SQL是(假设M2M表称为bookauthor
):
SELECT *
FROM book
WHERE
(SELECT ARRAY_AGG(bookauthor.author_id)
FROM bookauthor
WHERE bookauthor.book_id = book.id) = Array[1, 2];
您可以让Django几乎生成此SQL。
首先,pip install django-sql-utils
。然后创建这个Array
类:
from django.db.models import Func
class Array(Func):
function = 'ARRAY'
template = '%(function)s[%(expressions)s]'
现在您可以编写您的ORM查询集:
from sql_util.utils import SubqueryAggregate
from django.contrib.postgres.aggregates import ArrayAgg
books = Book.objects.annotate(
author_ids=SubqueryAggregate('author__id', Aggregate=ArrayAgg)
).filter(author_ids=Array(1, 2))
答案 2 :(得分:-2)
Q对象会对你有所帮助。的 Docs 强>
Book.objects.filter(Q(author__id=1) & Q(author__id=2))
答案 3 :(得分:-4)
您可以使用“IN”查询。 Django Docs
Book.objects.filter(author__id__in=[1,2])