You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中__range查询失效问题:Char字段数值范围查询异常

问题根源:字符串字典序 vs 数值大小比较

兄弟,你踩了个非常经典的坑——你的miles_from_warehouse是CharField字符串类型,而Django的__range查询对字符串字段是按字典序来筛选的,完全不是你预期的数值大小逻辑。

举个直观的例子:

  • 当你用("6", "26")做范围查询时,数据库会把所有字符串按字典顺序排列。像"10"、"15"这类字符串,第一个字符是'1',字典序里'1'比'6'小,所以它们会排在"6"的前面,自然不会被包含在"6"到"26"的范围内,因此查不到结果。
  • 但你把起始值改成"0"时,"0"的字典序比所有数字开头的字符串都靠前,所以所有数值在0-26之间的字符串(比如"10"、"26")都会被纳入筛选范围,就能查到数据了。
两种解决方案

方案1:彻底修改字段类型(推荐)

既然这个字段存的是数值,直接把CharField改成适合存储数值的类型才是长久之计:

# 在models.py中修改字段
# 如果是整数里程用IntegerField
miles_from_warehouse = models.IntegerField(verbose_name="仓库里程", ...)
# 如果是带小数的里程用DecimalField(比FloatField更精确)
miles_from_warehouse = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="仓库里程", ...)

改完后执行迁移命令更新数据库:

python manage.py makemigrations
python manage.py migrate

之后再用__range查询,就会按数值逻辑来筛选,完全符合你的预期。

方案2:临时转数值查询(不推荐长期使用)

如果暂时没法修改字段类型,可以通过Django的Cast函数把字符串转成数值后,用__gte和__lte做数值范围筛选:

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

# 先把字符串转成整数,再按数值范围查询
backwards_num = int(backwards)
frontwards_num = int(frontwards)
route = Route.objects.annotate(
    miles_as_int=Cast('miles_from_warehouse', IntegerField())
).filter(
    miles_as_int__gte=backwards_num,
    miles_as_int__lte=frontwards_num
)

这种方式能临时解决问题,但长期来看还是改字段类型更靠谱,避免后续再踩类似的坑。

内容的提问来源于stack exchange,提问作者zennn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:52:16