5

鉴于我有詹姆斯和尤金的作者。使用内置的__inQuerySet 将过滤匹配 James 或 Eugene 的 m2m 字段。但是,如果我只想要这两个匹配项怎么办。

示例设置:鉴于

authors = Author.objects.filter(interests__in=['python','ruby'])
# [<Author: James>, <Author: Eugene>]

这是我为正常情况所做的查询。它将返回任何包含 James 或 Eugene 或两者的书籍:

books = Book.objects.filter(authors__in=authors)
# [<Book: Book by James, Jack>, <Book: Book by Eugene>]

但目前,如果我想找到一本由 James 和 Eugene 共同撰写的书,我将不得不循环。

books = Book.objects
for author in authors:
    books = books.filter(authors=author)
# books [<Book: Book by James, Eugene>]

是否有一种优雅的方法可以直接对匹配两个给定值的 m2m 字段进行过滤。也许像

books = Book.objects.filter(authors__match=authors)
4

2 回答 2

3

您可以使用 Q 对象:

AND = lambda q, value: q & Q(authors_in=value)
Books.objects.filter(reduce(AND, authors, Q()))

如果您有作者列表而不仅仅是他们的 id,您还可以将 book_set 组合在一起:

books = reduce(lambda q,a: q & a.book_set.all(), authors, Book.objects.none())
于 2012-09-14T18:27:31.183 回答
0

您可以使用 & 运算符

# The list of authors you want to match
authors_pks = authors.values_list('pk', flat=True)

books = Book.objects

for pk in authors_pks:
    books &= Book.objects.filter(authors=pk)

print books.all()
于 2012-09-14T18:42:50.807 回答