迁移至MariaDB后Django查询变为大小写敏感的问题排查
Django迁移MariaDB后查询大小写敏感问题的原因与解决方法
问题原因
Django针对MySQL/MariaDB数据库,使用__contains查询时,会自动在生成的SQL语句中添加BINARY关键字,强制进行大小写敏感匹配,这会覆盖数据库排序规则(utf8mb3_general_ci)的不区分大小写特性。而你手动执行的SQL没有BINARY修饰,因此能正常利用排序规则实现不区分大小写查询,这就是代码查询和交互式查询结果不一致的核心原因。
解决方法
方法1:使用__icontains替换__contains
__icontains是Django专门提供的不区分大小写包含查询,生成的SQL不会添加BINARY关键字,完全利用数据库的_ci排序规则实现不区分大小写匹配,是最直接的解决方式。修改后的代码如下:
def get_queryset(self): query = self.request.GET.get('query') if query: query = " ".join(query.split()) if query.isdigit(): qs = Patient.objects.filter(Q(full_name__icontains=query) | Q(patient_id__icontains=query)).order_by('patient_id') else: qs = Patient.objects.filter(Q(full_name__icontains=query) | Q(patient_id__icontains=query)).order_by(Lower('full_name')) else: qs = Patient.objects.order_by(Lower('full_name')) return qs
方法2:指定模型字段的排序规则
如果希望继续使用__contains,可以在模型的对应字段上显式指定db_collation参数,确保模型层与数据库层的排序规则一致(即使你已设置数据库排序规则,显式指定字段级规则能避免潜在的不匹配问题):
class Patient(models.Model): full_name = models.CharField(max_length=255, db_collation='utf8mb3_general_ci') patient_id = models.CharField(max_length=50, db_collation='utf8mb3_general_ci') # 其他字段定义...
修改后需要生成并执行数据库迁移,更新字段的排序规则。
内容的提问来源于stack exchange,提问作者Andy Walldorff
相关产品推荐
相关产品推荐

