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>)
但这不会很好地扩展,而且您将检索到同一本书。
更好的方法是 Count
以 test
或 tester
作为名字的 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>)
或者因为 django-3.2, 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,并简单地计算匹配的作者数。
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>)
但这不会很好地扩展,而且您将检索到同一本书。
更好的方法是 Count
以 test
或 tester
作为名字的 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>)
或者因为 django-3.2, 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,并简单地计算匹配的作者数。