Django - Запрос: аннотировать Queryset с полями связанной модели - PullRequest
2 голосов
/ 17 апреля 2020

У меня есть следующая схема в Django с PostgreSQL.

Class Person (models.Model):
    name = models.CharField(max_length=255)
    email= models.CharField(max_legth = 255)
    created_at = models.DateTimeField()

Class PersonTask(models.Model):
   person = models.ForeignKey(Person)
   title = models.TextField()
   created_at = models.DateTimeField()

Class PersonHistory(models.Model):
   person = models.ForeignKey(Person)
   note = models.TextField()
   created_at = models.DateTimeField()

Теперь мне нужно запросить БД как все значения Person с последним PersonTask__title как max_task и самым последним PersonHistory__note as max_note

Например:

<Queryset: [
{name: "abc" ,email:"abc@gmail.com",created_at :"2019-01-02", max_task:"This is my latest tasktitle" , max_note: "This is my latest history note"},
{name: "abcd" ,email:"abcd@gmail.com",created_at :"2019-03-02", max_task:"This is my latest tasktitle for abcd" , max_note: "This is my latest history note for abcd"}
]>

Но, я мог бы получить максимум, это либо ID последней задачи и новейшей истории от

Person.objects.filter(customer_id= 1).\
               annotate( max_task = Max('persontask')).\
               annotate(max_note = Max('personhistory')).\
               order_by('-id')

Или случайный тексты задач или заметок с использованием запроса ниже

Person.objects.filter(customer_id= 1).\
               annotate( max_task = Max('persontask__title')).\
               annotate(max_note = Max('personhistory__note')).\
               order_by('-id')

Как это можно решить ??

Ответы [ 2 ]

0 голосов
/ 17 апреля 2020

Поскольку вы не упомянули ForeignKeys между этими моделями, я подозреваю, что Task и History имеют FK to Person в поле с именем person.

Я бы использовал Subquery с комбинацией OuterRef для выполнения этого запроса

from django.db.models import OuterRef, Subquery

result = (
    Person.objects
        .filter(customer_id=1)
        .annotate(
            task_title=Subquery(Task.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('title')[:1]),
            history_note=Subquery(HistoryNote.objects.filter(person=OuterRef('pk')).order_by('-created_at').values('note')[:1])
        )
        .order_by('-id')
)
0 голосов
/ 17 апреля 2020

Если задачи и история связаны с человеком, вам нужны отношения между вашими моделями. что-то вроде этого.

class PersonTask(models.Model):
    person = models.ForeignKey(Person, related_name="tasks", on_delete=models.CASCADE)
    title = models.TextField()
    created_at = models.DateTimeField()

class PersonHistory(models.Model):
    person = models.ForeignKey(Person, related_name="histories", on_delete=models.CASCADE)
    note = models.TextField()
    created_at = models.DateTimeField()

И тогда вы можете получить последнее задание и историю:

person = Person.objects.get(name="name")

person.tasks.last()
person.histories.last()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...