Django序列化器字段验证:调用is_valid时触发字符串格式校验异常
问题分析与解决方案
你的序列化器代码之所以没达到预期效果,核心原因是**CharField会自动将可转换为字符串的非字符串类型(比如数字、布尔值)转为字符串**。比如你传入state=123,CharField的to_internal_value方法会先把它转成"123",到validate_state方法里时,state已经是字符串了,isinstance(state, str)永远为True,自然不会抛出异常。
下面给你两种可行的解决方法:
方法一:自定义严格类型检查的CharField
继承CharField并重写to_internal_value方法,直接在字段解析阶段就拦截非字符串输入:
from rest_framework import serializers class StrictCharField(serializers.CharField): def to_internal_value(self, data): # 先检查类型,不通过直接抛异常 if not isinstance(data, str): raise serializers.ValidationError("state should be a string") # 类型符合的话,再走父类的逻辑(比如长度校验) return super().to_internal_value(data) class MySerializer(serializers.Serializer): state = StrictCharField(max_length=20, required=False)
这样调用serializer.is_valid(raise_exception=True)时,只要state不是字符串类型,就会立刻抛出异常。
方法二:在序列化器的validate方法中检查原始输入
直接读取序列化器的原始输入数据(未经过字段转换的),进行类型校验:
from rest_framework import serializers class MySerializer(serializers.Serializer): state = serializers.CharField(max_length=20, required=False) def validate(self, data): # 只有当state存在于原始输入中时才校验 if 'state' in self.initial_data: raw_state = self.initial_data['state'] if not isinstance(raw_state, str): raise serializers.ValidationError({"state": "state should be a string"}) return data
这种方法不需要自定义字段,直接利用序列化器的validate方法就能实现需求。
两种方法都能满足你调用is_valid(raise_exception=True)时触发异常的要求,根据你的偏好选择即可。
内容的提问来源于stack exchange,提问作者Rhavish qi
相关产品推荐
相关产品推荐

