代码之家  ›  专栏  ›  技术社区  ›  Adam Starrh

使用关联的模型和时间增量对对象进行排序

  •  0
  • Adam Starrh  · 技术社区  · 6 年前

    我手上有一个难题。作为练习,我试图写一个查询集,帮助我想象我应该优先与哪些专业联系人通信。

    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 反映与某个对象的单点接触 . A. 可能与许多人有相反的关系 ContactInstance 物体。

    那么,第一个呢 在queryset中,应该拥有 date 最近的 ContactInstance

    所以我的梦函数看起来像:

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

    但当然,由于各种原因,这是行不通的。

    我相信有人可以为此编写一些原始的PostgreSQL,但我真的很想知道是否有一种方法可以仅使用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]))
    

    null values at the end :

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

    但我不知道接下来该怎么办。我一直在努力把所有的东西都放进去 order_by() F() timedelta 就我而言。

    更新: 我改变了主意 模仿 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))
    

    在我看来,这应该是可行的,但是queryset仍然没有正确排序。

    0 回复  |  直到 6 年前