簡體   English   中英

Django 按日期訂購 model 並將沒有日期的型號移動到最后

[英]Django order model by date and move models without date to the end

我有一張model的票,里面有一筆錢。 我正在嘗試在最近的到期日之前制作消費票。 但如果我按date_expire訂購,它date_expire=None模型移到頂部。 但是date_expire=None表示ticket沒有時間限制,應該在所有有時間限制的ticket之后使用。

我的代碼:

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 中有更好的方法

更新程序

我想我為自己找到了解決方案。 現在我的代碼看起來像:

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 function 創建一個新值has_date ,它使用 SQL func IFNULL,如果字段date_expireNULL則返回True

查詢中的 SQL 字段必須是這樣的:

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

然后我首先按-has_date排序,將所有具有True值的對象移動到False值下。

也許有更好的方法來做到這一點,但該方法適合我的想法。

您可以將F表達式與nulls_firstnulls_last使用。 檢查 django 文檔中的使用 F() 對 null 值進行排序

在你的情況下:

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()

可能不是官方解決方案:

一種方法是引入一個代表上限值的值。 因此,不要將 None 用於 date_expire,而是使用未來 1000 年的日期,例如12/31/3000 這樣這個日期總是晚於您當前的日期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM