【问题标题】:Django 1.6: How to order a query set by a computed DateTimeFieldDjango 1.6:如何通过计算的 DateTimeField 对查询集进行排序
【发布时间】:2014-07-23 19:27:47
【问题描述】:

我有一个 项目 模型,其中包含 DateTimeField 和持续时间 PositiveIntegerField 字段。

该模型还有一个函数 days_left 实现相对复杂的逻辑来计算距离到期还剩多少天。该函数返回一个整数。

我想根据这个函数返回的值执行一个简单的查询集排序。

    Project.objects.all().order_by('days_left')

但是我不断收到一个例外,即 days_left 不是一个字段。

在本机 SQL 中是否有任何有效的方法(可能通过视图等)并绕过查询集,或者是否存在针对此类情况的 django 解决方案?

整个代码:

import datetime as nsdt
from django.db import models 
from django.utils import timezone

class Project(models.Model):
    name                        = models.CharField(max_length=128)
    publish_date                = models.DateTimeField()
    duration_days               = models.PositiveIntegerField() 

    def days_left(self):
        t1 = timezone.now()
        t2 = self.publish_date + nsdt.timedelta(days=self.duration_days)
        return (t2 - t1).days if t2 > t1 else 0


if __name__ == '__main__':

    print Project.objects.all().order_by('days_left')
    # throws excpetion: 
    #    django.core.exceptions.FieldError: Cannot resolve keyword 'days_left_computed' into field.

【问题讨论】:

    标签: python django sql-order-by django-queryset calculated-field


    【解决方案1】:

    由于排序是在数据库级别进行的,因此您不能为此使用 Django 的 order_by。相反,您可以尝试使用sorted() 对对象进行排序。

    projects = sorted(Project.objects.all(), key=lambda x: x.days_left())
    

    更新:

    由于您有大量记录,也许您可​​以使用Queryset.extra() 方法。 Source

    您可以尝试的另一种方法是使用django.db.models.F

    使用F() 的示例(免责声明:未经测试)

    from django.db.models import F
    
    projects = Project.objects.all().order_by((F('publish_date') + nsdt.timedelta(days=F('duration_days'))) - timezone.now())
    

    【讨论】:

    • 这个解决方案没问题,但我有数百万条记录。
    • 更新了答案并添加了一些可能的方法
    猜你喜欢
    • 2016-10-16
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 2018-03-22
    • 2021-11-30
    • 2010-12-11
    相关资源
    最近更新 更多