Заказ объектов с использованием связанной модели и timedelta - PullRequest
0 голосов
/ 30 мая 2020

У меня в руках загадка. В качестве упражнения я пытаюсь написать набор запросов, который поможет мне визуализировать, с какими из моих профессиональных контактов я должен отдавать приоритет переписке.

Для этого у меня есть пара моделей:

class Person(models.Model):
    name = models.CharField(max_length=256)
    email = models.EmailField(blank=True, null=True)
    target_contact_interval = models.IntegerField(default=45)

class ContactInstance(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='contacts')
    date = models.DateField()
    notes = models.TextField(blank=True, null=True)

Столбец target_contact_interval на модели Person обычно указывает максимальное количество дней, которое должно пройти, прежде чем я свяжусь с вами. снова этому человеку.

A ContactInstance отражает единственную точку контакта с Person. A Person может иметь обратную связь со многими ContactInstance объектами.

Итак, первый Person в наборе запросов должен обладать наибольшей разницей между date самых последних ContactInstance связанных к нему и самому себе target_contact_interval

Итак, функция моей мечты будет выглядеть примерно так:

Person.objects.order_by(contact__latest__date__day - timedelta(days=F(target_contact_interval))

, но, конечно, это не сработает по разным причинам.

Я уверен, что кто-то мог бы написать для этого необработанные PostgreSQL, но мне действительно любопытно узнать, есть ли способ выполнить sh это, используя только Django ORM.

Вот фрагменты, которые я нашел до сих пор, но у меня возникли проблемы с их соединением.

Возможно, я смогу использовать Subquery, чтобы отметить дату наиболее недавняя точка данных:

from django.db.models import OuterRef, Subquery
latest = ContactInstance.objects.filter(person=OuterRef('pk')).order_by('-date')
Person.objects.annotate(latest_contact_date=Subquery(latest.values('date')[:1]))

И мне нравится идея сортировки нулевых значений в конце :

from django.db.models import F
Person.objects.order_by(F('last_contacted').desc(nulls_last=True))

Но я не знаю, куда go отсюда. Я пытался поместить все в order_by(), но не могу понять, можно ли использовать F() с аннотированными значениями или с timedelta в моем случае.

ОБНОВЛЕНИЕ: У меня есть изменил модель target_contact_interval на DurationField, как было предложено. Вот запрос, который я пытаюсь использовать:

ci = ContactInstance.objects.filter(
    person=OuterRef('pk')
).order_by('-date')

Person.objects.annotate(
    latest_contact_date=Subquery(ci.values('date'[:1])
).order_by((
    (datetime.today().date() - F('latest_contact_date')) - 
    F('target_contact_interval')
).desc(nulls_last=True))

Мне кажется, что это должно сработать, однако набор запросов по-прежнему упорядочен неправильно.

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