Django:使用order_by排序数值

h3.*_*h3. 18 sorting django

我的情况是我必须通过用于存储街道地址的CharField输出相当大的对象列表.

我的问题是,显然数据是按ASCII码排序的,因为它是一个Charfield,具有可预测的结果..它按这样的数字排序;

1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 20, 21....
Run Code Online (Sandbox Code Playgroud)

现在明显的步骤是将Charfield更改为正确的字段类型(IntegerField让我们说),但它不能工作,因为某些地址可能有公寓......如"128A".

我真的不知道如何才能正确订购..

Dan*_*man 23

如果您确定该字段中只有整数,您可以通过该extra方法将数据库转换为整数,并按顺序排序:

MyModel.objects.extra(
    select={'myinteger': 'CAST(mycharfield AS INTEGER)'}
).order_by('myinteger')
Run Code Online (Sandbox Code Playgroud)

  • 由于 django 正在弃用 `extra()`,这里是如何使用 `annotate()` 做同样的事情:`MyModel.objects.annotate(myinteger=RawSQL('CAST(mycharfield AS UNSIGNED)', params=[])) .order_by('myinteger')` (4认同)
  • 如果您的MYSQL版本不支持,请使用'SIGNED'或'UNSIGNED'而不是INTEGER. (3认同)

dar*_*low 12

如果您正在使用PostgreSQL(不确定MySQL),您可以安全地在字符/文本字段上使用以下代码并避免强制转换错误:

MyModel.objects.extra(
    select={'myinteger': "CAST(substring(charfield FROM '^[0-9]+') AS INTEGER)"}
).order_by('myinteger')
Run Code Online (Sandbox Code Playgroud)


pra*_*ual 11

Django正试图弃用extra()方法,但已Cast()在v1.10中引入.在sqlite(至少)中,CAST可以采用诸如的值10a并将其转换为整数10,因此您可以执行以下操作:

from django.db.models import IntegerField
from django.db.models.functions import Cast

MyModel.objects.annotate(
    my_integer_field=Cast('my_char_field', IntegerField())
).order_by('my_integer_field', 'my_char_field')
Run Code Online (Sandbox Code Playgroud)

它将首先以数字方式返回按街道号排序的对象,然后按字母顺序返回,例如 ...14, 15a, 15b, 16, 16a, 17...

  • `Cast` 不支持诸如 `10a` 之类的值。如果它收到一个,它会抛出 `DataError: invalid input syntax for integer`。我通过删除值中的所有非数字字符(PostgreSQL)找到了一种解决方法:`from django.db.models.expressions import F, Value, Func` `queryset.annotate(my_integer_field=Cast( Func(F('my_char_field '), Value('[^\d]'), Value(''), Value('g'), function='regexp_replace'), IntegerField()) )` (2认同)

Yah*_*ran 5

我知道我\xe2\x80\x99m对此很晚,但因为它\xe2\x80\x99s与这个问题密切相关,而且我很难找到这个:

\n

你要知道你可以直接把它放在你的模型的选项Castordering

\n
from django.db import models\nfrom django.db.models.functions import Cast\n\n\nclass Address(models.Model):\n\n    street_number = models.CharField()\n\n    class Meta:\n        ordering = [\n            Cast("street_number", output_field=models.IntegerField()),\n        ]\n
Run Code Online (Sandbox Code Playgroud)\n

来自有关订购的文档:

\n
\n

您还可以使用查询表达式。

\n
\n

并来自有关数据库功能的文档:

\n
\n

函数也是表达式,因此它们可以与聚合函数等其他表达式一起使用和组合。\xc2\xa0

\n
\n