本文共 4657 字,大约阅读时间需要 15 分钟。
反序列化有 验证、保存 两个步骤。
实现步骤:
验证有三种方法:根据属性类型、根据属性参数、自定义方法验证。
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)
实现步骤:
1. 调用序列化对象的save()方法完成保存
serializer.save()
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接收到的数据)
知识点:
在对序列化器进行save()保存时,可以额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到:
serializer.save(owner=request.user)
转载地址:http://euxgz.baihongyu.com/