我在Django模型中订购两个日期时遇到问题。我有一个模型来保存文档记录,如下所示:
class Document(models.Model):
document_title = models.CharField(max_length=100)
document = models.FileField()
date_of_signature = models.DateField()
date_of_rectification = models.DateField(null=True, blank=True)
class Meta:
ordering = ['-date_of_signature', '-date_of_rectification']
我已经使用类Meta Options.ordering
来订购日期并通过订购获得了结果,但是我的具体问题是:
date_of_rectification
可以是null
的值,因此,如果它是null
,则必须使用最新的date_of_signature
进行订购,而我在类Meta {{ 1}} 我搜索了许多关于stackoverflow的问题,发现此MySQL查询Mysql order items by the newest of 2 dates恰好解决了我在MySQL数据库中的问题,并在Django Manager.raw()上实现了此查询,如下所示,我得到了预期的结果。但这并没有帮助我在 Django Admin 上订购数据,这不是我的要求。而且我还想知道是否可以使用RawQueryset插入的Django Queryset解决此查询。
Options.ordering
答案 0 :(得分:1)
您可以在两个字段中注释查询,以获取两个字段中的最大一个:
from django.db.models.functions import Greatest
Document.objects.annotate(
latest=Greatest('-date_of_signature', '-date_of_rectification')
).order_by('-latest')
关于管理员内的顺序,您可以覆盖get_queryset
方法以使用相同的注释:
from django.db.models import Count
class DocumentAdmin(admin.ModelAdmin)
def queryset(self, *args, **kwargs):
qs = super(DocumentAdmin, self).queryset(*args, **kwargs)
qs = qs.annotate(
latest=Greatest('-date_of_signature', '-date_of_rectification'))
)
return qs.order_by('-latest')
或者,如果上述方法不起作用(例如,空字段处理不是您想要的),则可以对这两个字段进行反规范化,从而创建第三个名为last_modified
的字段,其中{ {1}}和editable=False
。然后,您可以在db_index=True
上进行计算。按顺序排序该字段将在查询方面更加高效,但要付出更多数据库字段和几行代码的代价。
答案 1 :(得分:0)
尝试了许多选项之后,我找到了一种解决方案,可以使用django中的conditional Expressions获得所需的结果,如下所示:
Document.objects.annotate(
latest=Case(
When(date_of_rectification__isnull=True, then=F('date_of_signature')),
When(date_of_rectification__gte=F('date_of_signature'), then=F('date_of_rectification')),
default=F('date_of_rectification')
)
).order_by('-latest')
django将转换此代码的MySQL查询为:
SELECT myapp_document.document_title, myapp_document.document,
myapp_document.date_of_signature, myapp_document.date_of_rectification,
CASE WHEN myapp_document.date_of_rectification IS NULL THEN myapp_document.date_of_signature
WHEN myapp_document.date_of_rectification >= (myapp_document.date_of_signature) THEN myapp_document.date_of_rectification
ELSE myapp_document.date_of_rectification END AS latest FROM myapp_document ORDER BY latest DESC
但是我不确定它的效率如何。希望有更好的答案。