反序列化操作,APIView,GenericAPIView

2、反序列化操作

​ 反序列化流程——json数据----->字典----->校验---->模型类对象

​ 如果模型类字段有默认值 设置序列化器时 required=False 如果为必传参数 required=True

​ read_only = True指的是当前字段只作用于序列化操作

​ write_only = True指的是当前字段只作用于反序列化操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fk3NQoLr-1587053511032)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1578716208575.png)]

1.反序列化校验流程

​ 1.获取校验的字段数据

 book_info = {"id":9,"btitle":"狼图腾","bpub_date":"2020-1-11"}

​ 2.构建序列化器对象

 bs = BookInfoSerializer(data=book_info)  # data指明要校验的字典数据  data必须写

​ 3.启动校验步骤

bs.is_valid()  # 校验成功返回True  失败返回False

​ 4.当且仅当校验成功之后,才会生成有效数据

bs.validated_data  # 最终的有效数据
# 生成的数据 OrderedDict([('btitle', '狼图腾'), ('bpub_date', datetime.date(2020, 1, 11))])

​ 类型:字典 会根据字段指明的类型做适当的转换

​ 校验失败查看错误信息

bs.errors  # 查看校验失败的信息
# 如果校验失败  不会产生有效数据

2.校验的分类

​ 1.约束条件校验

​ 2.类型校验

​ 3.使用validators约束条件指明的单一字段校验函数——validators=列表或者是元组

# 校验单一字段
def check_btitle(value):
    """
    功能:校验btitle中包含django
    value为当前字段经过前序校验之后的数据
    :return:
    """
    if 'django' not in value:
        # 如果校验失败  通过抛异常的方式通知调用者(序列化器)校验失败
        # 必须抛出drf中的ValidationError异常,异常会被drf自动捕获,返回合适的响应对象
        raise  serializers.ValidationError('这不是一本关于django的书')
        
        
# 1、定义一个序列化器,来序列化BookInfo模型类对象
# Serializer: 是drf中自定义序列化器的基类
class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    # read_oly = True表示当前字段只作用于序列化操作,对于反序列化是新增  id会自动增加 因此id作用于序列化
    id = serializers.IntegerField(label='ID', read_only=True)


    # write_only = True 表示当前字段只能作用于反序列化操作
    btitle = serializers.CharField(label='名称',
                                   max_length=20,
                                   # write_only=True,
                                   validators=[check_btitle]
                                   )
    bpub_date = serializers.DateField(label='发布日期',
                                      required=True,
                                      )
    bread = serializers.IntegerField(label='阅读量', required=False)
    bcomment = serializers.IntegerField(label='评论量', required=False)
    image = serializers.ImageField(label='图片', required=False)

​ 4.通过自定义方法校验单一字段的校验函数:validate_校验的字段名

# 通过自定义方法来针对单一字段的校验
# validate_<字段名>
# 必须写在对应的序列化器内部
def validate_bpub_date(self, value):
    """
        日期要大于2020-1-1
        :param value: 经过前序校验的当前字段的数据,类型是date类型
        :return: 一定要返回经过本次校验之后产生的"有效数据"
        """
    if value <= date(year=2020, month=1, day=1):
        # 校验失败
        raise serializers.ValidationError("日期必须大于2020-1-1")

    return value

​ 5.重写validate函数为最后一步校验,返回值为最终的有效数据

# 必须写在对应的序列化器内部
def validated(self,attrs):
	"""
	自定义校验逻辑
	attrs:经过前序校验的所有字段的数据,类型是字典
	返回真正的有效数据
	"""
    print(type(attrs),attrs)
    # 类型是:<class 'collections.OrderedDict'> 
    # OrderedDict([('btitle', 'django新版'), ('bpub_date', datetime.date(2020,, 10))])
    return attrs

序列化器新建数据流程

校验成功之后,新建模型类对象
1.数据校验 产生有效数据(具体流程如下)

​ 1.1 准备数据

book = {"btitle":"django新版","bpub_date":"2020-1-11"}

​ 1.2构建序列化对象

bs = BookInfoSerializer(data=book)

​ 1.3开启校验

bs.is_valid()  # 返回True或者是False
bs.validated_data  # 查看有效数据
# OrderedDict([('btitle', 'django新版'), ('bpub_date', datetime.date(2020, 1, 10))])
# 校验成功之后,新建
bs.save()
2.校验成功之后,新建

​ 调用序列化器的save方法实现新建 save方法内部重写了create方法 自动传入数据

​ 前提:重写create方法 补充新建逻辑代码

# 创建模型类对象
def create(self, validated_data):
 	"""
    序列化器 用来新建模型类对象
    :param validated_data: 校验之后的有效数据
    :return: 返回新建的模型类对象
    """
    instance = BookInfo(**validated_data)
    instance.save()

    return instance

序列化器更新数据流程

校验成功之后 更新数据模型类对象

​ 第一步:数据校验,产生有效数据(具体流程如下)

​ 1.准备需要更新的数据和需要被更新的目标模型类对象

​ 2.构建序列化对象(data里面传入更新数据,instance传入被更新的模型类对象)

​ 3.启用校验

# 1.准备需要更新的数据
book_info = {"btitle":"django新版基础","bpub_date":"2020-1-5"}
# 需要操作的目标模型类对象
book = BookInfo.objects.get(pk=8)
# 2.构建序列化对象
bs = BookInfoSerializer(instance=book,data=book_info) 
# 3.启用校验
bs.is_valid()
# 4.保存更新的数据
bs.save()

​ 第二步:校验成功,更新数据(具体流程)

​ 1.重写序列化器里面的update方法

​ 2.调用序列化对象的save方法实现更新,save内部会调用重写update方法 自动传入被更新的对象 和有效数据

#更新模型类对象
def update(self, instance, validated_data):
    """
        更新模型类对象
        :param instance: 被更新的模型类对象
        :param validated_data: 更新的有效数据
        :return: 返回更新的模型类对象
        """
    new_btitle = validated_data['btitle']
    new_bpub_date = validated_data['bpub_date']

    instance.btitle = new_btitle
    instance.bpub_date = new_bpub_date
    instance.save()

    return instance

模型类序列化器

作用——1.自动映射模型类字段 2.不需要重写create、update方法

自定义序列化器——会把对应模型类的所有字段全部映射

from rest_framework import serializers
from .models import BookInfo,HeroInfo


class BookInfoModelSerializer(serializers.ModelSerializer):
    # 声明序列化或反序列化操作字段有哪些,针对的是哪个模型类
    class Meta:
        model=BookInfo  # 通过Meta的model类属性,指明当前序列化器操作的模型类为BookInfo
        fileds='__all__' # 把BookInfo模型类的所有字段  自动映射到序列化器
        #fileds=['btitle','bpub_date']  # 只映射btitle和bpub_date这两个字段  
class HeroInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        model=HeroInfo
        fileds='__all__'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCgJYp4a-1587053511035)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1578900985830.png)]

映射全部的字段会出现部分字段的值不合理,修改方法有两种:

第一种方法:在当前序列化器里面 显示定义的字段和类型 修改里面的数值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMrIkLUk-1587053511038)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1578745553111.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iTBiUvKq-1587053511041)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1578745567008.png)]

第二种方法:在class Meta 类里面有一个extra_kwargs字典 修改自动映射的约束条件

# 修改自动映射的约束条件
extra_kwargs={
    'bread':{'min_value':0}
}

用模型类序列化器也可以实现序列化和反序列化操作

# 序列化操作
    # 单个对象
    book = BookInfo.objects.all()[3]
    bs = BooksInfoModelSerializer(instance=book)
    bs.data
    # 多个对象
    book = BookInfo.objects.all()
    bs = BooksInfoModelSerializer(book,many=True)
    bs.data
    
# 反序列化操作
	# 创建单一对象
	book_info = {"btitle":"django新版","bpub_date":"2020-1-1"}
	bs = BooksInfoModelSerializer(data=book_info)
	bs.is_valid()
	bs.save()
	# 更新数据
	book_info = {"btitle":"django新版","bpub_date":"2020-1-6"}
	book = BookInfo.objects.get(pk=8)
	bs = BooksInfoModelSerializer(book,data=book_info)
	bs.is_valid()
	bs.save()

APIView视图函数

1.drf响应对象——Reseponse

​ 1.模块——from rest_framework.response import Response

​ 2.状态码模块——from rest_framework.status import HTTP_200_OK

​ 3.Reseponse(data={},status=状态码,headers={})

2.drf请求对象——request

request——drf对django的请求对象再次封装得到的请求对象

drf中提取查询字符串参数

request.query_params  # 得到的多值字典(一个key对应多个值)
request.query_params.get('key')  # 得到最后一个值
request.query_params.getlist('key')  #得到所有key所对应的值

drf中获取请求体参数(只能是json,form表单数据)

request.data  # 直接得到的是字典
#如果是自定义的请求体数据 则需要用request.body得到字节数据 转化 执行后续操作
3.APIView获取多个数据
from rest_framework.response import Response
from rest_framework.views import APIView
from  rest_framework.status import HTTP_200_OK,HTTP_201_CREATED,HTTP_400_BAD_REQUEST
from .serializer import *
from test_app.models import BookInfo,HeroInfo


class BooksInfoAPIView(APIView):
    def get(self,request):
        # 1.获取查询集
        book = BookInfo.objects.all()
        # 2.创建序列化对象
        serializer = BooksInfoModelSerializer(instance=book,many=True)
        # 3.序列化响应
        return Response(data=serializer.data,status=HTTP_200_OK)
3.APIView创建单一对象
def post(self,request):
    # 1.获取请求体数据
	book = request.data
	# 2.创建序列化对象
    serializer = BooksInfoModelSerializer(data=book)
    # 3.校验
    #if not serializer.is_valid():
		#return Response(data=serializer.errors,status=HTTP_400_BAD_REQUEST)
        
    # raise_exception=True:校验过程中失败了,不再返回True或者是False来提示
    # 而是直接把异常抛给视图函数  视图函数自动捕获异常并自动构建响应对象返回
    serializer.is_valid(raise_exception=True)
    # 4.新建
    serializer.save()
    # 5.返回序列化数据
    return Response(data=serializer.data) 

# 这里可以对校验进行简写  需要用到raise_exception
4.APIView获取单一对象
class BookInfoAPIView(APIView):
    # 获取单个对象
    def get(self,request,pk):
        # 获取数据
        book = BookInfo.objects.get(pk=pk)
        # 构建序列化器对象
        serializer = BooksInfoModelSerializer(book)
        # 序列化返回
        return Response(data=serializer.data)
5.更新数据——全部更新PUT和部分更新PATCH
# 更新数据  分为全部更新PUT和部分更新PATH
#  全部更新
def put(self,request,pk,**kwargs):
    partial_result = kwargs.get('partial',False)
    # 获取目标对象和更新数据
    book = BookInfo.objects.get(pk=pk)
    book_info = request.data
    # 创建序列化器对象
    serializer = BooksInfoModelSerializer(instance=book,data=book_info,partial=partial_result)
    # 校验(必传参数必须校验)
    serializer.is_valid(raise_exception=True)
    # 更新数据
    serializer.save()
    # 返回更新的序列化数据
    return Response(data=serializer.data,status=HTTP_201_CREATED)
# 部分更新
def patch(self,request,pk):
    return self.put(request,pk,partial=True)

# 因为部分更新和全部更新的代码逻辑相同  因此可以简化为调用put函数  但是需要注意部分更新需要传入partial=True  而在put函数里面需要传入**kwargs参数  当为部分更新kwargs.get('partial',False)等于True   为全部更新时False
6.删除数据
def delete(self,request,pk):
    # 删除数据
    book = BookInfo.objects.get(pk=pk)
    book.delete()
    return Response(data={},status=HTTP_204_NO_CONTENT)

GenericAPIView

重要的函数

def get_queryset(self):  # 获取序列化的目标数据查询集  多个对象
def get_object(self)  # 获取目标数据 单一对象
def get_serializer(self) # 创建序列化对象
def get_serializer__class(self)  # 获取序列化器类
获取查询集多个模型类对象——self.get_queryset()

实例方法——self.get_queryset()获取多个查询集 依赖类属性queryset 默认返回的就是类属性queryset指明 的查询集

类属性——queryset:指明当前的视图处理的默认的数据集

实例方法——self.get_serializer_class():获得处理查询集所使用的序列化器类,依赖类属性self.get_serializer

类属性——serializer_class:指明当前视图处理查询集所默认使用的序列化器

实例方法——self.get_serializer():构建一个序列化器对象 依赖queryset,serializer_class

from rest_framework.response import Response
from rest_framework.generics import GenericAPIView
from  rest_framework.status import HTTP_200_OK,HTTP_201_CREATED,HTTP_400_BAD_REQUEST,HTTP_204_NO_CONTENT
from .serializer import *
from test_app.models import BookInfo,HeroInfo


class BooksInfoAPIView(GenericAPIView):
    # 通过类属性queryset来声明设置当前视图默认处理的查询集
    queryset = BookInfo.objects.all()
    # 通过类属性serializer_class  设置当前视图默认处理查询集所用的序列化器
    serializer_class = BooksInfoModelSerializer  # 千万不要加()

    # 获取多个数据
    def get(self):
        # 获取查询集
        book_info = self.get_queryset()  # 这是一个泛指查询集  因此需要用queryset声明处理的查询集是哪一个
        # 创建序列化器对象
        # get_serializer也是一个泛指对象  因此需要用serializer_class声明是哪一个序列化对象
        serializer = self.get_serializer(instance=book_info,many=True)
        # 返回序列化数据
        return Response(data=serializer.data)
创建单个对象
# 创建单一数据
def post(self,request):
    # 获取前端数据
    # 创建序列化对象
    serializer = self.get_serializer(data=request.data)
    #  校验
    serializer.is_valid(raise_exception=True)
    # 保存数据
    serializer.save()
    # 返回序列化数据
    return Response(serializer.data)
获取单个对象
class BookInfoAPIView(GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BooksInfoModelSerializer

    # lookup_field = 'pk'  # 告诉get_object函数,按照pk字段去过滤
    # lookup_url_kwarg = 'pk'  # 过滤字段的值在哪个命名分组参数中提取

    def get(self,request,pk):
        # 获取单一数据数据
        book_info = self.get_object() # 这里需要声明按照什么去过滤和所需要的值
        # 创建序列化对象
        serializer=self.get_serializer(instance=book_info)
        # 序列化数据返回
        return Response(data=serializer.data)
    # 这里需要注意 drf默认是按照pk进行过滤
更新数据——全部更新和部分更新
# 全部更新
def put(self,request,pk,**kwargs):
    partial_result = kwargs.get('partial',False)

    book = self.get_object()
    serializer = self.get_serializer(instance=book,data=request.data,partial=partial_result)
    serializer.is_valid(raise_exception = True)
    serializer.save()
    return Response(data=serializer.data,status=HTTP_201_CREATED)

# 部分更新
def patch(self,request,pk):
    return self.put(request,pk,partical=True)
删除数据
# 删除
def delete(self,request,pk):
    book_info = self.get_object()
    book_info.delete()
    return Response(data={},status=HTTP_204_NO_CONTENT)

al’,False)

book = self.get_object()
serializer = self.get_serializer(instance=book,data=request.data,partial=partial_result)
serializer.is_valid(raise_exception = True)
serializer.save()
return Response(data=serializer.data,status=HTTP_201_CREATED)

部分更新

def patch(self,request,pk):
return self.put(request,pk,partical=True)


#### 删除数据

```python
# 删除
def delete(self,request,pk):
    book_info = self.get_object()
    book_info.delete()
    return Response(data={},status=HTTP_204_NO_CONTENT)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值