Django query with manytomany as list

Я работаю с django (4.1) и у меня проблема с QuerySet.

models.py

class Publication(models.Model):
    title = models.CharField(max_length=30)

    class Meta:
        ordering = ['title']

    def __str__(self):
        return self.title


class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)

    class Meta:
        ordering = ['headline']

    def __str__(self):
        return self.headline

python manage.py shell

>>> from many2many.models import Article, Publication
>>> qsA = Article.objects.values("id","headline","publications")
>>> qsP = Publication.objects.values("id","title")
>>> for a in qsA:
...     print(a)
... 
{'id': 1, 'headline': 'A', 'publications': 1}
{'id': 1, 'headline': 'A', 'publications': 2}
{'id': 2, 'headline': 'B', 'publications': 3}
{'id': 2, 'headline': 'B', 'publications': 4}
>>> for a in qsP:
...     print(a)
... 
{'id': 1, 'title': 'tA1'}
{'id': 2, 'title': 'tA2'}
{'id': 3, 'title': 'tB1'}
{'id': 4, 'title': 'tB2'}

>>> 

Я хотел бы иметь QuerySet, который возвращает "заголовок" Статьи, и список "заголовков" Публикации. Что-то вроде

{'headline': 'A', 'list_publications': 'tA1 tA2'}
{'headline': 'B', 'list_publications': 'tB1 tB2'}

Вы можете определить related_name, чтобы легко получить доступ к связанной модели через неявное отношение.
Если вы определите related_name="articles" внутри вашего M2M поля publications, вы сможете получить доступ к статьям, связанным с публикацией, вызвав my_publication.articles.all()

Чтобы вернуть названия, связанные с публикациями, вы можете сделать следующее:

Publication.objects.annotate(titles=___("articles__title"))

annotate() позволяет добавить в набор запросов столбец, не относящийся к таблице (обычно связанный или вычисляемый).
titles - имя этого дополнительного столбца.
___ - это имя функции агрегирования в данном случае (мы обсудим ее далее).
"articles" - это ваш related_name.
"title" - это столбец связанной модели, по которому вы хотите агрегировать.

Приведенный выше код агрегирует связанные названия для каждой публикации.

Итак, какую функцию агрегации использовать? Вот документация https://docs.djangoproject.com/en/4.1/topics/db/aggregation/.
Внутри ничего полезного для вашего вопроса нет, так что вам придется обратиться к функциям агрегации для конкретных БД.

Из того, что я знаю:
. Если вы используете Postgres, есть ArrayAgg, но это выведет ["t1", "t2"].
https://docs.djangoproject.com/en/4.1/ref/contrib/postgres/aggregates/.
Если вы используете MariaDB или MySQL, вы можете использовать GroupConcat.
https://django-mysql.readthedocs.io/en/latest/aggregates.html

Вернуться на верх