【问题标题】:Order by name with number Django按名称排序,编号为 Django
【发布时间】:2020-06-25 11:11:56
【问题描述】:

我在一个 sqlite 数据库中有大约 500 个设备对象,其中有一个 name 字段,例如:

Device-0
Device-1
Device-2
Device-3
...
...
Device-500

当用 django 列出这些时,我希望它根据名称中分号后面的数字列出,如上所示。

我试过了:

queryset = Device.objects.all().order_by('name')

也来自这个question

queryset = Device.objects.annotate(int_sort=Cast("name", IntegerField())).order_by("int_sort", "name")

这两个都会产生这个结果:

Device-0
Device-1
Device-10
Device-100
Device-101
...

任何帮助将不胜感激。

【问题讨论】:

  • 这能解决您的问题吗? stackoverflow.com/questions/34559094/…
  • 只需将所有设备对象重命名为 Device-XYZ。即 Device-001,Device-002.then 做你在第一个上面做的同样的事情

标签: python django django-queryset


【解决方案1】:

您正在寻找"natural sort" ("dictionary sort") order

这不是 SQLite 内置的(也不是我知道的任何其他数据库)。

如果您的所有行都遵循XYZ-123 格式,您可以

  • 添加一个 .extra() where= 列,其中的表达式用破折号分隔列,然后将第二部分转换为数字
  • 然后order_by 那个额外的列。

示例

这是一个可以在 SQLite shell 中运行的示例:

sqlite> create table device (name text);
sqlite> insert into device (name) values ('Device-1'),('Device-2'),('Device-3'),('Device-4'),('Device-5'),('Device-6'),('Device-7'),('Device-8'),('Device-9'),('Device-10'),('Device-11'),('Device-12'),('Device-13'),('Device-14'),('Device-15'),('Device-16'),('Device-17'),('Device-18'),('Device-19'),('Device-20'),('Device-21'),('Device-22'),('Device-23'),('Device-24'),('Device-25'),('Device-26'),('Device-27'),('Device-28'),('Device-29'),('Device-30'),('Device-31'),('Device-32'),('Device-33'),('Device-34'),('Device-35'),('Device-36'),('Device-37'),('Device-38'),('Device-39');
sqlite> select * from device order by name limit 10;
Device-1
Device-10
Device-11
Device-12
Device-13
Device-14
Device-15
Device-16
Device-17
Device-18
sqlite> select *, cast(substr(name,instr(name, '-')+1) as number) number from device order by number limit 10;
Device-1|1
Device-2|2
Device-3|3
Device-4|4
Device-5|5
Device-6|6
Device-7|7
Device-8|8
Device-9|9
Device-10|10

通过这个例子,你应该(但我没有验证,因为我手上没有合适的 Django 应用程序)能够做到

Device.objects.all().extra(
  select={'device_number': "cast(substr(name,instr(name, '-')+1) as number)"},
  order_by='device_number',
)

【讨论】:

  • 感谢您的回答。不过,我在将您的建议付诸实践时遇到了麻烦。你能举个例子吗?
  • 这太好了,非常感谢!你有非常广泛的知识。最后,只需很少修改即可工作:Device.objects.extra(select={'device_number': "cast(substr(name,instr(name, '-')+1) as number)"}).order_by('device_number')
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-25
  • 2021-07-06
  • 1970-01-01
  • 2013-08-22
  • 2023-04-11
  • 1970-01-01
  • 2013-07-21
相关资源
最近更新 更多