Проблема с агрегацией по аннотированным полям
У меня есть модели:
class Publisher(Model):
name = TextField()
class Author(Model):
name = TextField()
class Book(Model):
publisher = ForeignKey("Publisher")
author = ForeignKey("Author")
class Magazine(Model):
publisher = ForeignKey("Publisher")
writer = ForeignKey("Author")
Я хочу узнать, какие авторы писали для издательств. Моя версия такова:
from django.db.models import TextField, F, Subquery, OuterRef
from django.contrib.postgres.aggregates import StringAgg # I use postgres
# to lead to the same name
books = Book.objects.annotate(author_name=F("author__name"))
magazines = Magazine.objects.annotate(author_name=F("writer__name"))
books = books.values("publisher_id", "author_name")
magazines = magazines.values("publisher_id", "author_name")
product = books.union(magazines)
# !! here I have a problem with grouping
product = product.group_by(
"publisher_id"
).annonate(
author_names=StringAgg("author_name", ";")
)
publishers = Publisher.objects.all().annotate(
author_names=Subquery(
product.filter(publisher_id=OuterRef("id")).values("author_names")[:1],
output_field=TextField()
)
)
# I was expecting something like
# name | author_names
# ------------------------------------------
# Publisher1 | Author1;Author2;Author3
# Publisher2 | Author2
# Publisher3 | Author2;Author3
Проблема в том, что QuerySet не имеет метода .group_by(), вместо него предлагается метод .values() (product.values("publisher_id").annonate(...)).
Но это осложняется тем, что ранее я вызывал .values("publisher_id", "author_name"), чтобы привести две разные модели в одно представление.
Я также пробовал использовать .only("publisher_id", "author_name"), но (возможно, это ошибка Django) этот метод не может работать вместе с аннотированными и обычными полями.
Есть ли способ решить эту проблему или другой способ получить список авторов для издательства?