Django аннотировать, объединить несколько связанных значений на одном экземпляре - PullRequest
0 голосов
/ 10 мая 2019

У меня есть приложение django со следующими моделями:

class Person(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

class Job(models.Model):
    title = models.CharField(max_length=100)

class PersonJob(models.Model):
    person = models.ForeignKey(Person, related_name='person_jobs')
    job = models.ForeignKey(Job, related_name='person_jobs')
    is_active = models.BooleanField()

Несколько экземпляров Person могут одновременно выполнять одно и то же задание.У меня есть Job набор запросов, и я пытаюсь аннотировать или каким-либо другим способом прикрепить имена каждого человека с этим заданием к каждому элементу в наборе запросов.Я хочу иметь возможность циклически проходить через набор запросов и получать эти имена без выполнения дополнительного запроса для каждого элемента.Самое близкое, что я получил, это следующее:

 qs = Job.objects.all().annotate(first_names='person_jobs__person__first_name')
.annotate(last_names='person_jobs__person__last_name') 

Это будет хранить имя в экземпляре Job, как мне хотелось бы;однако, если в задании участвует несколько человек, в наборе запросов будет несколько копий одного и того же задания, каждое с именем одного человека.Вместо этого мне нужно, чтобы в наборе запросов был только один экземпляр заданного задания, в котором содержатся имена всех людей.Мне все равно, как значения объединяются и хранятся;список, поле с разделителями или любой другой стандартный тип данных будет в порядке.

Я использую Django 2.1 и Postgres 10.3.Я бы настоятельно предпочел не использовать какие-либо специфические функции Postgres.

1 Ответ

0 голосов
/ 10 мая 2019

Вы можете использовать ArrayAgg или StringAgg :

from django.contrib.postgres.aggregates import ArrayAgg, StringAgg  


Job.objects.all().annotate(first_names=StringAgg('person_jobs__person__first_name', delimiter=',')

Job.objects.all().annotate(people=ArrayAgg('person_jobs__person__first_name'))
...