7. 反序列化
反序列化有 验证、保存 两个步骤。
1. 验证
实现步骤:
- 定义序列化器类型,根据模型类定义、写属性、类型、参数
- 创建序列化器对象,以请求报文中的字典为参数
- 调用 is_valid() 方法,如果验证通过则返回True,验证失败返回False
- 验证通过时可以调用 validated_data 获取验证后的数据
- 验证失败可以通过 error_messages 获取错误信息
- 指定参数 raise_exception=True 将错误继续抛出
验证有三种方法:根据属性类型、根据属性参数、自定义方法验证。
1. 根据属性的类型验证
CharField、EmailField、IntegerField、DateField等,用户输入类型错误会报属性的类型错误。
2. 属性参数验证
demo:
btitle = serializers.CharField(min_length=3,max_length=10,
error_messages={
'min_length': '书名必须大于3个字符串',
'max_length': '书名必须小于10个字符串'})
bread = serializers.IntegerField(min_value=10, max_value=100)
id = serializers.IntegerField(read_only=True)
book_type = models.ForeignKey(Books, related_name='hero', on_delete=models.CASCADE, verbose_name='所属分类') # 外键
# 主键和关系属性(外键)必须设成只读:read_only = True
3. 自定义方法进行验证
自定义方法验证有三种方式:
-
validate_属性名称() : 针对 特定(单个)属性的值进行验证
# 验证书名的自定义方法<--在图书的序列化器内 def validate_btitle(self, attr): # attr 是请求报文中书名的数据,比如 笑傲江湖 # 要求: 书名中包含django字符串 if 'django' in attr: # 验证正常返回书名btitle return attr else: # 验证失败抛异常文本信息ValidationError raise serializers.ValidationError('书名中必须包含django')
-
validate() :针对多个值进行验证。内部参数是字典类型
# 自定义验证方式二: 将多个属性进行验证 def validate(self, attrs): # attrs 字典,可以接收所有请求报文中的数据 # 多用于多个对比,验证: 阅读量必须大于评论量 bread = attrs.get('bread') bcomment = attrs.get('bcomment') # 判断两个值都有才可以,request默认是True,我自己前边没指定,因此这个不用验证 if all([bread, bcomment]): if bread < bcomment: raise serializers.ValidationError('阅读量必须大于评论量') return attrs
-
validators=[参数] :参数是方法列表,定义参数的函数,针对特定属性进行验证。(该方法用的不多)
# 1.定义<---要把定义放到对应的序列化器上边 def check(value): # 验证: value必须是偶数,只判断不符合要求的情况,抛异常,正常不用管 if value % 2 != 0: raise serializers.ValidationError('必须为偶数') # 2.在序列化器中使用,对bread进行验证<--在bread限制条件内设置 # 因为是列表,因此可以写很多方法 validators=[check]
序列化器内定义反序列化的方法,然后在views视图内使用:
class BooksView(View):
""" 图书类视图 """
def post(self, request):
# 接收
params = json.loads(request.body.decode())
# 把接收的数据赋给data参数
book_ser = BookSerializer(data=params)
# 验证(调用 is_valid() 方法进行验证)
if book_ser.is_valid():
# 验证成功(保存步骤中会在验证成功后保存,此处暂时返回被验证的数据)
return JsonResponse(book_ser.validated_data)
else:
# 验证失败
return JsonResponse(book_ser.errors)
2. 保存
实现步骤:
- 在序列化器中定义create()和update()方法
- 在视图中创建序列化器对象,调用is_valid()和save()方法
1. 调用序列化对象的save()方法完成保存
serializer.save()
- save()方法包含create和update方法,可以自动调用,这两个方法需要自己在序列化器中创建。
- 如何知道save调用哪个方法:
查看序列化器内的参数 BookSerializer(instance=None, data=None)- 有模型类对象instance,是update操作;
- 没有模型类对象instance,是create操作。
2. 增加和修改之前先判断
-
增加 create()
当调用serializer.save()时,如果是增加就调用此方法,参数 validated_data 表示验证后的数据
def create(self, validated_data): # validated_data 表示验证后的数据,是字典类型 key:value # 拆包 **validated_data 拆成 key1:value1,key2:value2,... book = BookInfo.objects.create(**validated_data) return book
视图函数中创建新增方法:
class BooksView(View): """ 图书类视图 """ def post(self, request): # 接收 params = json.loads(request.body.decode()) # 把接收的数据赋给data参数 book_ser = BookSerializer(data=params) # 验证(调用 is_valid() 方法进行验证) if book_ser.is_valid(): # 验证成功(调用序列化器的save()方法进行保存) book = book_ser.save() # 验证成功返回被验证的数据 # return JsonResponse(book_ser.validated_data) # 保存成功之后返回新增的序列化器对象转成的字典数据 book_dict = BookSerializer(book).data return JsonResponse(book_dict, status=201) else: # 验证失败 return JsonResponse(book_ser.errors)
-
修改 update()
当调用serializer.save()时,如果是修改就调用此方法,参数 instance 需要被修改的对象,validated_data 验证后的数据
def update(self, instance, validated_data): # instance 需要被修改的对象, validated_data 验证后的数据 instance.btitle = validated_data.get('btitle') instance.bpub_date = validated_data.get('bpub_date') instance.save() return instance
视图函数中创建修改方法:
class BookView(View): """ 图书视图 """ def put(self, request, pk): """ 根据主键修改 """ params = json.loads(request.body.decode()) book = Books.objects.get(pk=pk) # serializer = BookSerializer(instance=book, data=params) serializer = BookSerializer(book, data=params) # instance是第一个参数,可以省略 if serializer.is_valid(): book = serializer.save() book_dict = BookSerializer(book).data return JsonResponse(book_dict, status=201) else: return JsonResponse(serializer.errors)
-
说明:(param_dict接收到的数据)
- 如果进行create添加操作,则serializer=**Serializer(data=param_dict)
- 如果进行update修改操作,则serializer=**Serializer(模型类对象,data=param_dict)
知识点:
-
在对序列化器进行save()保存时,可以额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到:
serializer.save(owner=request.user)