Django按日期排序模型,并将没有日期的模型移到最后

agxfikkp  于 2023-02-06  发布在  Go
关注(0)|答案(2)|浏览(123)

我有一个模型票,里面有一个金额。我试图在最近的到期日制作消费票。但如果我按date_expire订购,它会将date_expire=None模型移到顶部。但date_expire=None意味着该票没有时间限制,应该在所有票之后使用,这是有时间限制的。
我的代码:

ticket = Tickets.objects.filter(
                sum__gte=0,
                date_expire__gte=timezone.now(),
                user_id=user.id,
                burned=False
            ).order_by(
                'date_expire'
            ).first()

我可以尝试用带lambda键的sorted func来排序,但是我认为在orm中有更好的方法来完成

UPD

我想我找到了一个解决方案。现在我的代码看起来像:

ticket = Tickets.objects.filter(
                sum__gte=0,
                date_expire__gte=timezone.now(),
                user_id=user.id,
                burned=False
            ).annotate(
                has_date=Func(F('date_expire'), Value(None), function='IFNULL')
            ).order_by(
                '-has_date',
                'date_expire'
            ).first()

我使用QuerySetannotate函数生成一个新值has_date,该值使用SQL函数IFNULL,如果字段date_expireNULL,则返回True
查询中的SQL字段必须如下所示:

IFNULL("tickets"."date_expire", NULL) AS "has_date"

然后我首先按-has_date排序,将所有具有True值的对象移动到False值之下。
也许有一个更好的方法来做到这一点,但这种方法对我的想法有效。

muk1a3rh

muk1a3rh1#

您可以将F表达式与nulls_firstnulls_last一起使用。请查看django文档中的使用F()对空值进行排序。
在您的情况下:

from django.db.models import F

ticket = Tickets.objects.filter(
            sum__gte=0,
            date_expire__gte=timezone.now(),
            user_id=user.id,
            burned=False
        ).order_by(
            F('date_expire').desc(nulls_last=True)
        ).first()
pgvzfuti

pgvzfuti2#

可能不是官方的解决方案:
一种方法是引入一个表示上限值的值。因此,不要为date_expire使用None,而是使用1000年后的日期,如12/31/3000。这样,该日期总是晚于当前日期。

相关问题