Могу ли я сделать запрос в Django, который возвращает список по каждому элементу?
У меня есть 3 таких модели:
class Person(models.Model):
name = models.CharField(max_length=100)
class Place(models.Model):
name = models.CharField(max_length=100)
# ManyToMany Through Table
class PersonPlace(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
place = models.ForeignKey(Place, on_delete=models.CASCADE)
PersonPlace
связывает Person
и Place
в отношениях ManyToMany.
Мне нужен запрос к базе данных, который даст мне список мест id
на человека (список мест, которые посетил каждый человек).
Можно ли сделать агрегацию через ORM, не используя Python?
вернет список мест для одного человека
person_object = Person.objects.get(name="admin")
place_objects_ids_query_set = PersonPlace.objects.filter(person=person_object).values_list('place', flat=True)
place_objects_ids_list = list(place_objects_ids_query_set)
print(place_objects_ids_list)
в случае, если вам нужен список мест для многих людей
persons_objects = Person.objects.all()
place_objects_ids_query_set = PersonPlace.objects.filter(person__in=persons_objects).values_list('place', flat=True)
place_objects_ids_list = list(place_objects_ids_query_set)
print(place_objects_ids_list)
Если вы используете postgres, вы можете воспользоваться ArrayAgg
[Django-doc]:
from django.contrib.postgres.aggregates import ArrayAgg
for person in Person.objects.annotate(places=ArrayAgg("personplace__place")):
print(person.__dict__)
Это дает результат:
# ommitted unnecessary keys
{'id': 1, 'name': '1', 'places': ['2', '3']}
{'id': 2, 'name': '2', 'places': ['1', '2', '3']}
Под капотом все это делается на вашей базе данных с помощью следующего запроса:
SELECT
"person"."id",
"person"."name",
ARRAY_AGG("personplace"."place_id" ) AS "places"
FROM
"person"
LEFT OUTER JOIN
"personplace"
ON
("person"."id" = "personplace"."person_id")
GROUP BY
"person"."id"