使用相关对象的外键预取或注释 Django 模型
Prefetch or annotate Django model with the foreign key of a related object
假设我们有以下模型:
class Author(Model):
...
class Serie(Model):
...
class Book(Model):
authors = ManyToManyField(Author, related_name="books")
serie = ForeignKey(Serie)
...
如何获得作者列表及其系列?
我尝试了 annotate
和 prefetch
的不同组合:
list_authors = Author.objects.prefetch(Prefetch("books__series", queryset=Serie.objects.all(), to_attr="series"))
尝试使用 list_authors[0].series
会引发异常,因为 Author
没有 series
字段
list_authors = Author.objects.annotate(series=FilteredExpression("books__series", condition=Q(...))
尝试使用 list_authors[0].series
会引发异常,因为 Author
没有 series
字段
list_authors = Author.objects.annotate(series=F('books__series'))
returns 具有共同书籍的(作者,系列)的所有可能组合
当我在我的数据库中使用 PostgreSQL 时,我试过:
from django.contrib.postgres.aggregates import ArrayAgg
...
list_authors = Author.objects.annotate(series=ArrayAgg('books__serie', distinct=True, filter=Q(...)))
它工作正常,但 returns 只有 id
个相关对象。
list_authors = Author.objects.annotate(series=ArrayAgg(
Subquery(
Serie.objects.filter(
livres__auteurs=OuterRef('pk'),
...
).prefetch_related(...)
)
))
失败,因为它需要 output_field
,而 Model
不是 output_field
的有效值
但是
我可以得到作者的系列数,所以为什么不能得到它们的实际列表:
list_authors = Author.objects.annotate(nb_series=Count("books__series", filter=Q(...), distinct=True)
list_authors[0].nb_series
>>> 2
因此我认为我尝试做的事情是可能的,但我对 "How"...
感到茫然
我不认为你可以用 Author
查询集上的注释来做到这一点 - 因为你已经发现你可以 F('books__series')
但那不会 return 不同结果。通常只有当结果是每行一个值时注释才有意义。
你可以做的是在 Author
模型上使用一个方法,通过相对简单的查询获取该作者的所有系列。这将意味着每个作者一个额外的查询,但我看不到任何替代方案。像这样:
class Author:
def get_series(self):
return Serie.objects.filter(book__authors=self).distinct()
然后你就这样做:
list_authors = Author.objects.all()
list_authors[0].get_series()
假设我们有以下模型:
class Author(Model):
...
class Serie(Model):
...
class Book(Model):
authors = ManyToManyField(Author, related_name="books")
serie = ForeignKey(Serie)
...
如何获得作者列表及其系列?
我尝试了 annotate
和 prefetch
的不同组合:
list_authors = Author.objects.prefetch(Prefetch("books__series", queryset=Serie.objects.all(), to_attr="series"))
尝试使用 list_authors[0].series
会引发异常,因为 Author
没有 series
字段
list_authors = Author.objects.annotate(series=FilteredExpression("books__series", condition=Q(...))
尝试使用 list_authors[0].series
会引发异常,因为 Author
没有 series
字段
list_authors = Author.objects.annotate(series=F('books__series'))
returns 具有共同书籍的(作者,系列)的所有可能组合
当我在我的数据库中使用 PostgreSQL 时,我试过:
from django.contrib.postgres.aggregates import ArrayAgg
...
list_authors = Author.objects.annotate(series=ArrayAgg('books__serie', distinct=True, filter=Q(...)))
它工作正常,但 returns 只有 id
个相关对象。
list_authors = Author.objects.annotate(series=ArrayAgg(
Subquery(
Serie.objects.filter(
livres__auteurs=OuterRef('pk'),
...
).prefetch_related(...)
)
))
失败,因为它需要 output_field
,而 Model
不是 output_field
但是 我可以得到作者的系列数,所以为什么不能得到它们的实际列表:
list_authors = Author.objects.annotate(nb_series=Count("books__series", filter=Q(...), distinct=True)
list_authors[0].nb_series
>>> 2
因此我认为我尝试做的事情是可能的,但我对 "How"...
感到茫然我不认为你可以用 Author
查询集上的注释来做到这一点 - 因为你已经发现你可以 F('books__series')
但那不会 return 不同结果。通常只有当结果是每行一个值时注释才有意义。
你可以做的是在 Author
模型上使用一个方法,通过相对简单的查询获取该作者的所有系列。这将意味着每个作者一个额外的查询,但我看不到任何替代方案。像这样:
class Author:
def get_series(self):
return Serie.objects.filter(book__authors=self).distinct()
然后你就这样做:
list_authors = Author.objects.all()
list_authors[0].get_series()