Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django filter on m2m fields that matches all of the values given

Tags:

python

django

Given that I've an Author of James and Eugene. Using the built-in __in QuerySet will filter m2m fields that matched either James or Eugene. But how if I want only those matches both.

Example SetUp: Given that

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

Here's a query's that I've made for a normal condition. It will return any books that have either James or Eugene or Both:

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

But at the moment if I want to find a book which was written by both James and Eugene, I will have to do a loop.

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

is there an elegant way to do an filter on the m2m fields directly that match both of the given values. Perhaps something like

books = Book.objects.filter(authors__match=authors)
like image 329
Yeo Avatar asked Oct 22 '22 09:10

Yeo


1 Answers

You can use the Q object:

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

You can also AND together the book_set, if you have a list of Author instead of just their ids:

books = reduce(lambda q,a: q & a.book_set.all(), authors, Book.objects.none())
like image 88
Lie Ryan Avatar answered Oct 30 '22 18:10

Lie Ryan