python在django中按两个日期对数据库中的数据进行排序

nnsrf1az  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(283)

我有一个问题,订购两个日期在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 但我在元课上没有 Options.ordering 我在stackoverflow上搜索了很多问题,找到了这个mysql查询mysql order items最新的两个日期,正好解决了我在mysql数据库中的问题,在django manager.raw()上实现了这个查询,得到了预期的结果。但这并没有帮助我订购数据的django管理这不是我的要求。我还想知道这个查询是否可以用django queryset而不是rawqueryset来解决。

Model.objects.raw("""SELECT * FROM document
                ORDER BY IF(date_of_rectification > date_of_signature,
                date_of_rectification, date_of_signature)""")
eivnm1vs

eivnm1vs1#

在尝试了这么多选项之后,我找到了一个解决方案,使用django中的条件表达式可以得到所需的结果,如下所示:

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

但我不确定它的效率有多高。希望有更好的答案。

jmp7cifd

jmp7cifd2#

您可以在这两个字段上对查询进行注解,并获取其中最大的一个字段:

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 哪个有 editable=False 以及 db_index=True . 然后你就可以计算它了 save() . 对该字段进行排序将使查询效率更高一些,代价是需要更多的数据库字段和几行额外的代码。

相关问题