假设我们有以下模型:
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'))
返回所有拥有共同书籍的(作者,意甲)所有可能组合
当我在数据库中使用PostgreSQL时,我尝试了:
from django.contrib.postgres.aggregates import ArrayAgg
...
list_authors = Author.objects.annotate(series=ArrayAgg('books__serie', distinct=True, filter=Q(...)))
它工作正常,但仅返回相关对象的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
因此,我认为我可以做的事情是可能的,但是我对“如何做”感到茫然……
答案 0 :(得分:1)
我认为您无法在Author
查询集上添加注释,因为您已经发现可以执行F('books__series')
,但是不会返回不同的结果。通常,仅当结果为每行一个值时,注释才有意义。
您可以做的是在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()