Django ORM中icontains查询结果不一致的解决方法(只读库场景)
解决Django操作只读MySQL时icontains区分大小写的问题
因为你的数据库字段value_name使用的是utf8mb4_0900_bin二进制排序规则,而managed=False的模型中设置db_collation不会生效(Django不会修改只读数据库的字段属性),所以icontains会严格区分大小写。可以用以下两种方法解决:
方法一:使用extra()直接编写SQL片段
通过在查询中转换字段的排序规则或统一转为小写,实现不区分大小写的匹配:
方案1:统一转为小写匹配
search_lower = search.lower() queryset = MyModel.objects.extra( where=['LOWER(value_name) LIKE %s'], params=['%' + search_lower + '%'] ).order_by("pk")
方案2:转换字段排序规则
直接在SQL中指定排序规则进行匹配:
queryset = MyModel.objects.extra( where=['CONVERT(value_name USING utf8mb4) COLLATE utf8mb4_general_ci LIKE %s'], params=['%' + search + '%'] ).order_by("pk")
方法二:使用Django的Lower函数注解
通过annotate生成字段的小写版本,再进行过滤:
from django.db.models.functions import Lower queryset = MyModel.objects.annotate( value_name_lower=Lower('value_name') ).filter(value_name_lower__icontains=search.lower()).order_by("pk")
注意:如果数据量较大,方法二可能会因为全表扫描影响性能,优先推荐方法一的SQL片段方式。
内容的提问来源于stack exchange,提问作者Cool Breeze
相关产品推荐
相关产品推荐

