Django的多对多相交滤波(Django Many To Many intersection fi

2019-08-01 04:56发布

为了简单起见,让我们说,我只有2种型号:书,作者

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

class Book(models.Model):
    name = models.CharField(max_length='100')
    authors = models.ManyToManyField(Author)
    ...

我想筛选使用作者的列表书籍。 我试图做的是:

authors = [...] # a list of author objects
Books.objects.filter(authors__in=authors)

但在这里,作者将时,我想他们与运算或运算。 有没有什么办法,许多一对多过滤?

Answer 1:

你可以一起&一堆Q对象:

q = Q()
for author in authors:
    q &= Q(authors=author)
Books.objects.filter(q)

要排除的书有名单之外的作者,你可以限制查询到书籍列表中的作者数完全:

Books.objects.annotate(count=Count('authors')).filter(count=len(authors)).filter(q)

更新:

根据意见,我认为需求是获得至少一个作者列表中的所有创作的书籍,但名单之外的任何作家排除书籍。

因此,我们建立了一个queryset的选择,我们讨厌作者:

# this queryset will be embedded as a subquery in the next
bad_authors = Author.objects.exclude(name__in=['A1', 'A2'])

然后排除他们找到我们想要的书:

# get all books without any of the bad_authors
Books.objects.exclude(authors__in=bad_authors)

这将返回所有书籍,除了那些由您的名单之外的人撰写。 如果你也想排除那些没有列出的作者,再添排除电话:

Books.objects.exclude(authors__in=bad_authors).exclude(authors=None)

这将使我们能够仅仅通过一个或多个好的撰写的书!



文章来源: Django Many To Many intersection filtering