在 django 中按模型字段的子字符串对对象进行排序

Posted

技术标签:

【中文标题】在 django 中按模型字段的子字符串对对象进行排序【英文标题】:Sort objects by a substring of a model field in django 【发布时间】:2019-07-30 11:16:37 【问题描述】:

我试图找到最佳解决方案来对我的数据库中的所有 Machine 对象进行排序并找到最后使用的 deviceSerialNo。

deviceSerialNo 是一个字符字段,结构如下:AB12-12344。

我的任务是通过 deviceSerialNo 字段的子字符串对所有 Machine 对象进行排序(deviceSerialNo 中“-”之后的所有内容。 我目前的解决方案很有效

last = Machine.objects.all().order_by('-deviceSerialNo').first().deviceSerialNo

last2 = Machine.objects.all().order_by('-deviceSerialNo').annotate(search_index=StrIndex('deviceSerialNo', V('-'))).first().deviceSerialNo

有人可以帮我按照我上面提到的那样对它进行排序吗?

【问题讨论】:

'-'之前的部分是否总是4个字符? 不,不是。它会根据选择的模型而变化 【参考方案1】:

您可以按使用 annotate 创建的字段排序:

from django.db.models import IntegerField, Value as V
from django.db.models.functions import Cast, StrIndex, Substr

last = (
    Machine.objects.annotate(
        part=Cast(Substr("deviceSerialNo", StrIndex("deviceSerialNo", V("-"))), IntegerField())
    )
    .order_by("part")
    .first()
    .deviceSerialNo
)

就像你让我们从获取- 字符的索引开始:

StrIndex('deviceSerialNo', V('-'))

然后我们使用Substr 得到包含- 字符的第二部分:

Substr("deviceSerialNo", StrIndex("deviceSerialNo", V("-")))

然后我们把它转换成一个IntegerField,排序得到第一个对象。注意:我们可以得到第一个对象,因为"-12344" 的整数转换是一个负数。

【讨论】:

如何更改此代码,使其现在将检查正则表达式匹配:AB123-02506 并仅获取 -02 之后的数字? -02 之后的数字现在只会增长 而数字 -02 可以是 01 到 12 之间的任何值 @ikkuh 有没有办法获取字符最后一个索引的索引?例如,如果字符串改为 AB-12-12344. 不确定“字符的最后一个索引的索引”是什么意思。您可能想提出一个新问题。【参考方案2】:

如果数字有多个 - 并且想从反向中提取数字然后尝试跟随。 AB-12-12344

输出:12344

qs.annotate(
   r_part=Reverse('number')
).annotate(
   part=Reverse(
        Cast(
             Substr("r_part", 1, StrIndex("r_part", V("-")))
        ), 
        IntegerField()
    )

)

谢谢

【讨论】:

以上是关于在 django 中按模型字段的子字符串对对象进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在 django(postgres 后端)中按数字字符串排序查询结果

如何在搜索栏中按布尔字段过滤 - django

在django模板中按降序对相关项目进行排序

Django,在模型中按函数过滤 Q 对象

Django,在模型外键中按组过滤用户

如何在 Django 中按计算字段复杂排序?