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)
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())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With