“length”和“name”排序参数不符合我的要求

2024-10-05 20:05:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个PhysicalServer模型:

class PhysicalServer(models.Model):
    name = models.CharField(max_length=32)
    cabinet = models.ForeignKey(to=Cabinet, on_delete=models.DO_NOTHING, related_name="physical_servers")
    physical_server_model = models.ForeignKey(to=PhysicalServerModel, null=True, on_delete=models.DO_NOTHING)
    ...

    class Meta:
        ordering = ['-cabinet', '-physical_server_model', 'name']

其列表API视图如下:

^{pr2}$

我的physicalserver实例名称如下:


我的问题是,当我使用这个列表排序时:

^{3}$

结果将是:

SE01-A1
SE01-A2
SE01-A3
...
SE01-A9
SE01-C1
SE01-C2
SE01-C3
...
SE01-A10
SE01-A11
SE01-A12
...

如果我使用下面的排序:

return qs.annotate(length=Length('name')).order_by('name', 'length')

结果将是:

SE01-A1
SE01-A11
SE01-A12
SE01-A13
...
SE01-A2
SE01-A21
...
SE01-A3
...

我怎么能这样分类:

SE01-A1
SE01-A2
SE01-A3
SE01-A4
...
SE01-A10
...
SE01-C1
SE01-C2
...

是吗?在


Tags: tonamea2onmodelsa1deletelength
3条回答

你需要从字符串中提取数字。Postgres和mysql提供regexp_replace函数(我不确定其他数据库)。但是Django没有提供实现,所以我们将编写自己的function

from django.db.models import Func, Value

class RegexpReplace(Func):
    function = 'REGEXP_REPLACE'

    def __init__(self, expression, search, replace, **extra):
        search = Value(search)
        replace = Value(replace)
        super(RegexpReplace, self).__init__(expression, search, replace, **extra)

我假设你想把名字拆分到末尾的数字,然后你想用前半部分排序,然后用末尾的数字排序。(这对您来说很好,直到您开始在连字符之前获得3位数字,即SE99-A1、SE100-A1)。在

^{pr2}$

如果服务器名称的格式始终是server-code,并且没有出现其他连字符,则可以在连字符上拆分并按如下方式排序:

qs = sorted(qs, key: lambda i: (i.name().split('-')[1], len(i.name())))

注意:这不会返回查询集。在

使用Substr将名称的第一部分与末尾的数字分开,然后首先按这个新注释排序。在

from django.db.models.functions import Substr, Length
qs = qs.annotate(letters=Substr('name', 1, 6), length=Length('name'))
qs = qs.order_by('letters', 'length', 'name')
return qs

相关问题 更多 >