I have such a Book model:
class Book(models.Model): authors = models.ManyToManyField(Author, ...) ...
In short:
I'd like to retrieve the books whose authors are strictly equal to a given set of authors. I'm not sure if there is a single query that does it, but any suggestions will be helpful.
In long:
Here is what I tried, (that failed to run getting an AttributeError)
# A sample set of authors target_authors = set((author_1, author_2)) # To reduce the search space, # first retrieve those books with just 2 authors. candidate_books = Book.objects.annotate(c=Count('authors')).filter(c=len(target_authors)) final_books = QuerySet() for author in target_authors: temp_books = candidate_books.filter(authors__in=[author]) final_books = final_books and temp_books
... and here is what I got:
AttributeError: 'NoneType' object has no attribute '_meta'
In general, how should I query a model with the constraint that its ManyToMany field contains a set of given objects as in my case?
ps: I found some relevant SO questions but couldn't get a clear answer. Any good pointer will be helpful as well. Thanks.
The sql query will be like SELECT * FROM mytable WHERE ids=[1, 3, 6, 7, 9] which is not true. You have to use in operator for this so you query will be like SELECT * FROM mytable WHERE ids in (1, 3, 6, 7, 9) for that Django provide __in operator.
all() Returns a copy of the current QuerySet (or QuerySet subclass). This can be useful in situations where you might want to pass in either a model manager or a QuerySet and do further filtering on the result.
This exception is also an attribute of the model class. Returns a new QuerySet containing objects that match the given lookup parameters. Basically use get() when you want to get a single unique object, and filter() when you want to get all objects that match your lookup parameters. Show activity on this post.
The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.
Similar to @goliney's approach, I found a solution. However, I think the efficiency could be improved.
# A sample set of authors target_authors = set((author_1, author_2)) # To reduce the search space, first retrieve those books with just 2 authors. candidate_books = Book.objects.annotate(c=Count('authors')).filter(c=len(target_authors)) # In each iteration, we filter out those books which don't contain one of the # required authors - the instance on the iteration. for author in target_authors: candidate_books = candidate_books.filter(authors=author) final_books = candidate_books
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