Python 'length'和'name'排序参数不符合我的要求

Python 'length'和'name'排序参数不符合我的要求,python,django,django-rest-framework,Python,Django,Django Rest Framework,我有一个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.ForeignK

我有一个
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视图如下所示:

class PhysicalServerListAPIView(ListAPIView):
    serializer_class = PhysicalServerListSerializer
    permission_classes = [AllowAny]
    pagination_class = CommonPagination
    def get_queryset(self):
        qs = PhysicalServer.objects.filter(**filters)
        return qs.annotate(length=Length('name')).order_by('length', 'name') # there if I put the `name` first(order_by('name', 'length')), also inconformity my requirement.
我的physicalserver实例名称如下所示:


我的问题是,当我将此用于列表排序时:

return qs.annotate(length=Length('name')).order_by('length', 'name')
结果将是:

SE01-A1
SE01-A2
SE01-A3
...
SE01-A9
SE01-C1
SE01-C2
SE01-C3
...
SE01-A10
SE01-A11
SE01-A12
...
SE01-A1
SE01-A11
SE01-A12
SE01-A13
...
SE01-A2
SE01-A21
...
SE01-A3
...
如果我使用以下选项进行排序:

return qs.annotate(length=Length('name')).order_by('name', 'length')
结果将是:

SE01-A1
SE01-A2
SE01-A3
...
SE01-A9
SE01-C1
SE01-C2
SE01-C3
...
SE01-A10
SE01-A11
SE01-A12
...
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
...

用于将名称的第一部分与末尾的数字分开,然后首先按此新注释排序

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

您需要从字符串中提取数字。Postgres和mysql提供了
regexp\u replace
功能(我不确定其他数据库)。但是Django没有提供实现,因此我们将编写自己的:

我假设您希望将名称拆分为末尾的数字,然后使用前半部分进行排序,最后是数字。(这对您来说很好,直到您开始获得连字符前面的3位数字,即SE99-A1、SE100-A1)


这可能适用于我的情况,但在我的情况下,
名称几乎是固定的,因此,是否有更好的方法来实现这一点?例如,如果长度不是固定的,则不能对substr使用
1,6
。您可以根据需要多次重复此策略,迭代
name
的可能性,但在某些情况下,必须将字段固定为特定格式,以便任何类型的排序都能正常工作。另一种方法是将字段拆分为多个字段,其中包含构成名称的基本组件(这是我的建议),或者考虑编写一些数据库函数——当然,格式越复杂,运行查询所需的时间就越长。您正在寻找所谓的“自然排序”。请参见类似问题:,,在第二个代码段中,它不应该是
RegexpReplace
而不是
RegexpReplace2