Django агрегация Many To Many в список dict

Уже несколько часов я пытаюсь выполнить эту операцию, но так и не смог разобраться.

Допустим, у меня есть проект Django с двумя классами, такими как:

from django.db import models

class Person(models.Model):
   name=models.CharField()
   address=models.ManyToManyField(to=Address)

class Address(models.Model):
   city=models.CharField()
   zip=models.IntegerField()

Итак, это простое лицо, имеющее несколько адресов. Затем я создаю несколько объектов:

addr1=Address.objects.create(city='first', zip=12345)
addr2=Address.objects.create(city='second', zip=34555)
addr3=Address.objects.create(city='third', zip=5435)
person1=Person.objects.create(name='person_one')
person1.address.set([addr1,addr2])
person2=Person.objects.create(name='person_two')
person2.address.set([addr1,addr2,addr3])

Теперь начинается самая сложная часть, я хочу сделать один запрос, который вернет что-то вроде этого:

result = [
    {
      'name': 'person_one',
      'addresses': [
          {
            'city':'first',
            'zip': 12345
          },
          {
              'city': 'second',
              'zip': 34555
          }
      ]  
    },
    {
        'name': 'person_two',
        'addresses': [
            {
                'city':'first',
                'zip': 12345
            },
            {
                'city': 'second',
                'zip': 34555
            },
            {
                'city': 'third',
                'zip': 5435
            }
        ]
    }
]

Лучшее, чего я смог добиться, это использование операторов ArrayAgg и JSONBAgg для Django (я на POSTGRESQL BY THE WAY):

from django.contrib.postgres.aggregates import JSONBAgg, ArrayAgg
result = Person.objects.values(
   'name',
   addresses=JSONBAgg('city')
)

Но этого недостаточно, я не могу вытащить лит словарей из запроса напрямую, как я хотел бы сделать, только список значений или что-то бесполезное, используя:

addresses=JSONBAgg(('city','zip'))

который возвращает словарь со случайными ключами и строками, которые я передал в качестве входных данных в качестве значений.

Может кто-нибудь мне помочь?

Спасибо

По-моему, вы уже задавали тот же вопрос здесь , но не ответили на комментарии.

Нашли ли вы решение проблемы? Со своей стороны, мне пришлось создать отдельный набор запросов, чтобы получить результаты, но я думаю, что это не является удовлетворительным решением.

person.address уже содержит набор адресов. Отсюда вы можете использовать list-comprehension / model_from_dict для получения нужных вам значений.

Ваше требование: Сделать агрегацию настроенных JSON объектов после group_by (значения) в Django.

В настоящее время, насколько мне известно, Django не предоставляет никакой функции для агрегации созданных вручную JSON объектов. Есть несколько способов решить эту проблему. Во-первых, сделать настраиваемую функцию, что довольно трудоемко. Однако есть и другой подход, который довольно прост: использовать обе агрегатные функции (ArrayAgg или JSONBAgg) и RawSQL вместе.

from django.contrib.postgres.aggregates import JSONBAgg, ArrayAgg
result = Person.objects.values('name').annotate(addresses=JSONBAgg(RawSQL("json_build_object('city', city, 'zip', zip)", ())))

Надеюсь, это поможет вам.

Если вы используете postgres, вы можете сделать следующее:

subquery = Address.objects.filter(person_id=OuterRef("pk")).annotate(
    data=JSONObject(city=F("city"), zip=F("zip"))
).values_list("data")

persons = Persons.objects.annotate(addresses=ArraySubquery(subquery))
Вернуться на верх