反序列化验证

反序列化使用分为验证和保存更新

1. 验证分为:

字段验证

自定义方法验证

使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

验证成功,可以通过序列化器对象的validated_data属性获取数据。

在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

如我们前面定义过的BookInfoSerializer

# 自定义序列化器
class BookSerialzier(serializers.Serializer):
    # 序列化返回字段
    btitle = serializers.CharField(max_length=20,min_length=5)
    bread = serializers.IntegerField(max_value=100,min_value=5)
    # 如果没有选项参数就是必传参数,默认值是required=True
    bpub_date = serializers.DateField()
    # 当required=False,可以不传递参数
    # bpub_date = serializers.DateField(required=False)
    # 当没有传递此字段时,使用的是默认值10,而不会报错
    bcomment = serializers.IntegerField(default=10)

通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证

通过 python manage.py shell 命令窗口执行如下代码显示结果如下:

from book_drf.serializer import BookSerialzier
data = {'bpub_date': 123}
ser = BookSerialzier(data=data)
ser.is_valid()  # 返回False
ser.errors
# {'btitle': [ErrorDetail(string='This field is required.', code='required')], 'bread': [ErrorDetail(string='This field is required.',
code='required')], 'bpub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY-MM-DD.', code='invalid')]}
ser.validated_data
# {}


from book_drf.serializer import BookSerialzier
data = {'btitle': 'python','bread': 5,'bpub_date': '2022-10-10'}
ser = BookSerialzier(data=data)
ser.is_valid()  # True
ser.errors  # {}
ser.validated_data
#OrderedDict([('btitle', 'python'),
             ('bread', 5),
             ('bpub_date', datetime.date(2022, 10, 10)),
             ('bcomment', 10)])

通过post接收参数进行测试

book_drf目录下views.py代码如下:

import json

from django.http import JsonResponse
from django.views import View

from book_drf.serializer import BookSerialzier
from books.models import BookInfo


class Books(View):
    def get(self, request):
        # 1、查询所有图书对象
        books = BookInfo.objects.all()
        ser = BookSerialzier(books, many=True)
        return JsonResponse(ser.data, safe=False)
    def post(self, request):
        # 1获取前端数据
        data = request.body.decode()  # 得到一个json的字符串
        data_dict = json.loads(data)  # 转换成字典形式
        # 2验证数据
        ser = BookSerialzier(data=data_dict)
        ser.is_valid()  # 验证方法
        # 3保存数据
        # 4返回结果
        print(ser.validated_data)
        return JsonResponse(ser.errors)


class Book(View):

    def get(self, request):
        book = BookInfo.objects.get(id=1)
        ser = BookSerialzier(book)

        return JsonResponse(ser.data)

通过Postman发送的测试数据为:

{
    "btitle":"射雕英雄",
    "bread":1,
    "bpub_date":"1980-5-1"
}

返回会结果为,但状态码是200:

{
    "btitle": [
        "Ensure this field has at least 5 characters."
    ],
    "bread": [
        "Ensure this value is greater than or equal to 5."
    ]
}

python后端  print(ser.validated_data) 打印的结果为:{}

 is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)

修改python代码如下:

    def post(self, request):
        # 1获取前端数据
        data = request.body.decode()  # 得到一个json的字符串
        data_dict = json.loads(data)  # 转换成字典形式
        # 2验证数据
        ser = BookSerialzier(data=data_dict)
        ser.is_valid(raise_exception=True)  # 验证方法
        # 3保存数据
        # 4返回结果
        print("抛出异常不会执行后面的程序")
        print(ser.validated_data)
        return JsonResponse(ser.errors)

 通过Postman发送的测试数据为:

{
    "btitle":"射雕英雄",
    "bread":1,
    "bpub_date":"1980-5-1"
}

抛出异常为:

raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'btitle': [ErrorDetail(string='Ensure this field has at least 5 characters.', code='min_length
')], 'bread': [ErrorDetail(string='Ensure this value is greater than or equal to 5.', code='min_value')]}