在Django REST查询过滤器中使用.upper()及大小写统一后值对比的可行性问询
Django REST 大小写校验与匹配的实现方案
当然可以实现这两个需求!作为经常和Django REST打交道的开发者,我来给你具体说说怎么做:
1. 在查询过滤器中使用.upper()进行校验
直接在ORM过滤器里写field.upper()是行不通的,但我们可以借助Django的Upper数据库函数,实现字段值转大写后的精准匹配。这里分两种常见场景:
场景一:使用django-filter的FilterSet
如果你的项目用django-filter做查询过滤,可以自定义过滤方法:
from django_filters import FilterSet, CharFilter from django.db.models.functions import Upper from .models import YourModel class YourModelFilter(FilterSet): # 自定义过滤字段,指定处理方法 name = CharFilter(method='filter_name_case_insensitive') def filter_name_case_insensitive(self, queryset, name, value): # 给查询集添加转大写后的字段别名,再执行过滤 return queryset.annotate(upper_name=Upper(name)).filter(upper_name=value.upper()) class Meta: model = YourModel fields = ['name']
场景二:在视图的get_queryset中处理
如果不用django-filter,直接在视图里处理查询参数也很方便:
from django.db.models.functions import Upper from rest_framework.generics import ListAPIView from .models import YourModel from .serializers import YourModelSerializer class YourModelListView(ListAPIView): queryset = YourModel.objects.all() serializer_class = YourModelSerializer def get_queryset(self): queryset = super().get_queryset() name_param = self.request.query_params.get('name') if name_param: # 转大写后执行精确匹配 queryset = queryset.annotate(upper_name=Upper('name')).filter(upper_name=name_param.upper()) return queryset
2. 将数据库值与request.data的值均转大写后对比
这个需求通常出现在校验场景(比如更新时检查值是否一致)或者唯一性校验中,同样可以通过转大写来实现:
示例:在序列化器的validate方法中处理
from rest_framework import serializers from django.db.models.functions import Upper from .models import YourModel class YourModelSerializer(serializers.ModelSerializer): def validate(self, data): # 处理更新场景:对比数据库现有值和请求值的大写形式 if self.instance: db_field_value = self.instance.your_field.upper() request_field_value = data.get('your_field', '').strip().upper() if db_field_value != request_field_value: raise serializers.ValidationError("字段值与数据库记录不匹配(大小写不敏感)") # 处理创建场景:检查数据库中是否存在相同大写的值 if data.get('your_field'): request_upper = data['your_field'].strip().upper() exists = YourModel.objects.annotate(upper_field=Upper('your_field')).filter(upper_field=request_upper).exists() if exists: raise serializers.ValidationError("该字段值已存在(大小写不敏感)") return data class Meta: model = YourModel fields = '__all__'
小提示
如果只是需要不区分大小写的匹配,Django ORM的__iexact查询也能实现,但如果是强制要求转成大写后再严格对比,用Upper函数会更可靠,避免数据库collation设置带来的差异。
内容的提问来源于stack exchange,提问作者Jamshy
相关产品推荐
相关产品推荐

