为什么Django REST Framework序列化器的validate_width校验不生效
问题原因分析
- DRF 的
validate_<字段名>字段级校验规则,仅会对序列化器显式声明/包含的字段生效。你的ImageUploadSerializer的Meta.fields中只声明了['id', 'url', 'picture']三个字段,width并没有被纳入序列化器的校验字段范围,即便你在构造序列化器时传入了width参数,序列化器也会直接忽略该字段,不会触发对应的validate_width校验逻辑。 - 你在视图中虽然定义了专门用于接收参数的
ImageResizeSerializer,但完全没有调用它做请求参数校验,直接从request.data中取了width和height,相当于这个序列化器的定义完全没有生效。 - 即便后续你让
validate_width生效,当前create方法中也会直接读取图片本身的宽高覆盖你传入的width参数,校验逻辑的结果也不会影响最终落库的数据。
修复方案
- 调整
ImageUploadSerializer的字段配置,把width、height纳入校验范围:
class ImageUploadSerializer(serializers.ModelSerializer): picture = Base64ImageField() # 显式声明width、height字段,若模型中已存在对应字段,也可以直接加到下方fields列表中 width = serializers.IntegerField() height = serializers.IntegerField() class Meta: model = ImageUpload # 补充width、height到字段列表 fields = ['id', 'url', 'picture', 'width', 'height'] def validate_width(self, value): if value < 100: raise serializers.ValidationError('Width shouldn\'t be less then 100') return value def create(self, validated_data): im = Image.open(validated_data['picture']) # 如果需要校验用户传入的width,就不要用图片本身的width覆盖传入参数 # 如果你实际需要校验的是图片本身的宽度,就不需要传width参数,直接在校验逻辑中读取图片尺寸判断即可 # validated_data['width'] = im.size[0] # validated_data['height'] = im.size[1] validated_data['name'] = f'{datetime.datetime.now()}' return super().create(validated_data)
- 调整视图逻辑,先调用
ImageResizeSerializer校验请求参数,再走后续逻辑:
class ResizeImageView(APIView): serializer_class = ImageResizeSerializer def post(self, request, *args, **kwargs): # 先校验请求参数 param_serializer = self.serializer_class(data=request.data) param_serializer.is_valid(raise_exception=True) width = param_serializer.validated_data['width'] height = param_serializer.validated_data['height'] with open('c:/Users/KK/Desktop/tiny-kitten-in-sunlight.jpg', 'rb') as img: mock_resized_obj = img.read() mock_resized_obj_64 = pybase64.b64encode_as_string(mock_resized_obj) serializer = ImageUploadSerializer( data={'picture': mock_resized_obj_64, 'width': width, 'height': height} ) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
内容的提问来源于stack exchange,提问作者Vlad Vlad
相关产品推荐
相关产品推荐

