Bernd Wechner
Bernd Wechner

Reputation: 2143

Django: get all objects with a defined set of related objects

Let's say we have a many2many relationship as follows:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=100) 
    authors = models.ManyToManyField(Author, related_name="books")

and now I have a known set of Authors:

authors = Author.objects.filter(...)

How can I get all the books that are authored by that exact set of authors?

books = Book.objects.filter(X)

what is X? Such that I have all the books authored by exactly that set of authors?

I have tried, just because:

books = Book.objects.filter(authors__in=authors)

But nah, that returns the books to which any of those authors contributed it seems. I want the books that all of those authors contributed to and only those authors.

Thus far, this has stumped me.

Upvotes: 1

Views: 126

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477676

You can check if the number of matching authors is the amount of authors, so:

from django.db.models import Count, Q

nauthors = authors.count()

Book.objects.alias(
    nauthors=Count('authors'),
    nmatch_authors=Count('authors', filter=Q(authors__in=authors)),
).filter(
    nauthors=nauthors,
    nmatched_authors=nauthors
)

It is important that authors does not contain duplicates.

Upvotes: 2

Related Questions