django orm 多个过滤器在相同的多对多字段上

django orm multiple filter on same many to many field

class Book(models.Model):
    title = models.CharField(max_length=50)
    authors = models.ManyToManyField(Author)

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)

假设我想要至少有两位作者的书,他们的名字分别是 Test 和 Tester.So 我将继续 Book.objects.filter(authors__first_name='Test').filter(authors__first_name='Tester')

如果我有多个名字(长列表)要检查,除了 运行 for 循环和 rawsqlquery 还有其他选择吗?

queryset = Book,objects.all()
for i in ['test','tester']:
   queryset = queryset.filter(authors__first_name=i)

您应该过滤:

datas = ['test', tester']
qs = Book.objects.all()
for datum in datas:
    qs = qs.filter(<strong>authors__first_name=datum</strong>)

但这不会很好地扩展,而且您将检索到同一本书。

更好的方法是 Counttesttester 作为名字的 Author 的数量:

datas = set(['test', 'tester'])

Book.objects.filter(
    <strong>authors__first_name__in=datas</strong>
).annotate(
    nauthors=Count('authors')
).filter(<strong>nauthors=len(data)</strong>)

或者因为 , we can make use of the .alias(…) [Django-doc] 防止计数两次(一次用于过滤器,一次用于 SELECT 子句):

datas = set(['test', 'tester'])

Book.objects.filter(
    authors__first_name__in=datas
)<strong>.alias(</strong>
    nauthors=Count('authors')
<strong>)</strong>.filter(nauthors=len(data))

这里我们将一个加入Author模型的table,并简单地计算匹配的作者数。