Если вам не нужно искать по нему, я бы создал свойство на модели проекта. Вы можете использовать функцию Max
для aggregate
, чтобы получить запись с самой новой датой.
from django.db.models import Max
class Project(models.Model):
[...]
@property
def status_date(self):
return self.projectstatus_set.aggregate(newest=Max('status_date'))['newest']
Эта стратегия задокументирована здесь .
Если вам нужно выполнить поиск, то вам следует денормализовать и добавить поле в Project
. Вы можете сохранить его текущим, используя сигналы. Вы бы хотели добавить слушателя post_save
в ваше поле ProjectStatus
, которое установило бы дату его проекта в статус '.
from django.db.signals import post_save
def update_status_date(sender, instance=None, **kwargs):
project = instance.project
project.status_date = max(project.status_date, instance.status_date)
project.save()
post_save.connect(update_status_date, sender=ProjectStatus)
Подробнее о сигналах можно прочитать здесь .
======
РЕДАКТИРОВАТЬ: С момента написания моего первоначального ответа, ОП несколько прояснил свой вопрос, и его разъяснение изменяет пример кода для обеих моих стратегий, хотя не их базовую конструкцию. Я хочу оставить первоначальный ответ тем, кому, возможно, нужны более родственные вопросы, на которые, как мне казалось, я отвечал в то время.
В моем первом примере он на самом деле не хочет самой новой даты status_date, а скорее самого нового типа статуса проекта. Это существенно изменило бы свойство; вам вообще не нужно использовать SQL-конструкцию MAX()
; Вы просто хотите, чтобы первая запись была прикреплена к этому объекту, когда упорядочено по убыванию даты:
class Project(models.Model):
[...]
@property
def project_status(self):
return self.status.order_by('-status_date')[0]
Варианты использования вокруг этого все те же. Если вы всегда сначала получаете проект, а затем хотите узнать его текущее состояние, то это правильный путь. Если вам нужно индексировать проектов по статусу, то вам нужно денормализовать. Лучше всего это сделать с помощью сигналов, но вместо сохранения даты, как я делал в моем примере выше, вы, вероятно, захотите сохранить описание. Принцип остается тем же, хотя.