Django 4.1.1中contains/startswith查询不区分大小写,如何强制区分?
如何让Django的contains/startswith查询强制区分大小写
出现这种情况的核心原因是数据库字段的排序规则(collation)设置为不区分大小写,导致Django的contains/startswith这类原本应该区分大小写的查询,实际执行时被数据库忽略了大小写差异。以下是几种解决办法:
1. 修改数据库字段的排序规则(推荐)
直接调整字段的排序规则,从根源上解决问题,不同数据库的操作方式如下:
MySQL/MariaDB
如果你的name字段使用的是utf8mb4_general_ci(默认不区分大小写),改成utf8mb4_bin或utf8mb4_unicode_cs(大小写敏感):
在Person模型中添加db_collation参数:
class Person(models.Model): name = models.CharField(max_length=100, db_collation='utf8mb4_bin')
然后生成并执行迁移:
python manage.py makemigrations python manage.py migrate
PostgreSQL
如果字段是citext类型(天生不区分大小写),改成普通varchar;或者指定区分大小写的排序规则(比如C,严格按ASCII码比较):
class Person(models.Model): name = models.CharField(max_length=100, db_collation='C')
执行迁移即可生效。
2. 在查询时强制区分大小写(无需修改字段)
如果不想改动数据库结构,可以在查询语句中加入强制大小写的逻辑:
MySQL/MariaDB
使用BINARY操作符强制按二进制比较:
from django.db.models import Func, Value def index_filter(request, name_filter): # 强制区分大小写的contains查询 case_sensitive_results = Person.objects.filter( name__contains=Func(Value(name_filter), function='BINARY') ).count() case_insensitive_results = Person.objects.filter(name__icontains=name_filter).count() context = {'case_sensitive_results': case_sensitive_results, 'case_insensitive_results': case_insensitive_results} return render(request, 'index2.html', context)
PostgreSQL
如果字段是citext类型,先转成普通text再查询:
from django.db.models import Func, F def index_filter(request, name_filter): case_sensitive_results = Person.objects.filter( Func(F('name'), function='TEXT').contains(name_filter) ).count() case_insensitive_results = Person.objects.filter(name__icontains=name_filter).count() context = {'case_sensitive_results': case_sensitive_results, 'case_insensitive_results': case_insensitive_results} return render(request, 'index2.html', context)
3. 验证效果
修改后重新运行视图,对比两个计数的数值差异,如果case_sensitive_results小于case_insensitive_results,说明区分大小写已经生效。
内容的提问来源于stack exchange,提问作者chakmeshma
相关产品推荐
相关产品推荐

