[英]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()
我使用QuerySet
的annotate
function 創建一個新值has_date
,它使用 SQL func IFNULL,如果字段date_expire
是NULL
則返回True
。
查詢中的 SQL 字段必須是這樣的:
IFNULL("tickets"."date_expire", NULL) AS "has_date"
然后我首先按-has_date
排序,將所有具有True
值的對象移動到False
值下。
也許有更好的方法來做到這一點,但該方法適合我的想法。
您可以將F
表達式與nulls_first
或nulls_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.