drf APIView 序列化类 及 序列化,反序列化使用

drf APIView 序列化类 及 序列化,反序列化使用

1、APIView基本使用

drf:是一个第三方的app,只能在django 上使用
安装drf后,导入一个视图类 为APIView,所有后期要使用drf与视图类,都是继承APIView及其子类

获取所有的图书接口

1.1、使用View+JsonResponse写

from rest_framework.views import APIView

from rest_framework.response import Response
from rest_framework.request import Request

class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        # queryset 对象 不能直接序列化 只能通过 for循环 一个个拼成列表套字典
        data_list = []
        for book in book_list:
            data_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return JsonResponse(data_list,safe=False,json_dumps_params={'ensure_ascii':False})

1.2、使用APIView+drf的Response写

不要忘了注册rest_framework这个app

from rest_framework.views import APIView

from rest_framework.response import Response
from rest_framework.request import Request

class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        # queryset 对象 不能直接序列化 只能通过 for循环 一个个拼成列表套字典
        data_list = []
        for book in book_list:
            data_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(data_list)

2、ApIView 源码分析

视图类继承APIView后,执行流程发生了变化,这个变化就是整个drf的执行流程

**APIView 继承了 View **
路由 执行 先执行 APIView中 重写的View 然后又在其中 调用了 父类View的as_view返回了as_view的view 并且 利用装饰器 取消了 csrf的 验证

from rest_framework.views import APIView

from rest_framework.response import Response
from rest_framework.request import Request

class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        # queryset 对象 不能直接序列化 只能通过 for循环 一个个拼成列表套字典
        data_list = []
        for book in book_list:
            data_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(data_list)

真正的执行,执行self。dispatch>>>>APIView的dispatch【重点】

 def dispatch(self, request, *args, **kwargs):
        # 参数的request是原来的django原生的request
        # 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
        request = self.initialize_request(request, *args, **kwargs)
        # self 是视图类的对象,视图类对象.request=request 等于的是新的request
        self.request = request
        try:
            # 执行了认证,频率,权限 [不读]
            self.initial(request, *args, **kwargs)
            # 原来的View的dispatch的东西
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                 self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            response = handler(request, *args, **kwargs)
        except Exception as exc:
            # 如果出了异常,捕获异常,处理异常,正常返回
            # 在执行三大认证和视图类中方法过程中,如果出了异常,是能被捕获并处理的---》全局异常的处理
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

总结

  1. 只要继承APIView都没有csrf的认证了
  2. 以后视图类中使用request对象,已经变成了drf提供的Request类的对象了
  3. 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
  4. 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

3、Request类源码分析

视图类中使用的request 是这个类的对象,已经变成了drf提供的Request类的对象了
原生django 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest
drf的request是这个类的对象:rest_framework.request.Reques

request已经不是原来的request了,还能像原来的request一样使用吗
用起来,像之前一样

print(request.method)  # get
print(request.path)  # /books/
print(request.GET)   # 原来的get请求提交的参数
print(request.POST)  # 原来post请求提交的参数

Request的源码分析:rest_framework.request.Request
类中有个魔法方法:__getattr__ 对象 点 属性,属性不存在会触发它的执行

def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来
        try:
            #反射:根据字符串获取属性或方法,self._request 是原来的request
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)

以后用的所有属性或方法,直接用就可以了>>>(通过反射去原来的request中取)

新的request内部有个老的request,就是request._request

data 是个方法,被property装饰了,成了数据属性用
原来 urlencoded,form-data——提交的数据在request.POST中
json格式提交的数据,在request.POST中没有,它在request.body中

现在无论哪种格式,都从request.data中取

query_parms:get请求提交的参数,等同于`reqeust._request.GET 或 request。GET
其他: 取文件也是从request.FILES中取,跟之前一样

reqeust.dataurlencoded,form-data格式 获取的是QueryDict, 在json格式 获取的是字典

4、序列化组件介绍

是drf提供的一个类,我们继承它,写自己的类

用来序列化 querydict或单个对象的

获取所有图书接口>>>QueryDict或book对象 转成json格式字符串,给前端

drf提供了一种可以快速实例化的类:序列化类

5、序列化的基本使用

5.1、定义一个序列化类

在app中创建一个 py文件(serializer)

from  rest_framework import serializers
class BookSerializer(serializers.Serializer):
    # 要序列化的字
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

5.2、使用序列化类,序列多条数据

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serializer import BookSerializer
class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list,many=True)

        return Response(ser.data)

5.3、使用序列化类,序列化单条数据

class Book_s_View(APIView):
    def get(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)

6、反序列化

6.1、新增

from app01.serializer import BookSerializer
class BookView(APIView):
    def post(self,request):
        # 前端数据 从requestdata 取出
        ser = BookSerializer(data=request.data)
        if ser.is_valid(): # 对传入的数据 进行的校验
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

需要重写 create方法
在serializer 文件 序列化类下重写create方法

def create(self, validated_data):
    res=Book.objects.create(**validated_data)
    return res

6.2、修改

class Book_s_View(APIView):
        def put(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        # 前端数据 从requestdata 取出
        ser = BookSerializer(instance=book_obj,data=request.data)
        if ser.is_valid(): # 对传入的数据 进行的校验
            ser.save()
            return Response(ser.data)

重写 update 方法
同样 updata方法 需要我们自己写

def update(self, instance, validated_data):
    instance.name = validated_data.get('name')
    instance.price = validated_data.get('price')
    instance.publish = validated_data.get('publish')
    instance.save()
    return instance

6.3、删除

class Book_s_View(APIView):
        def delete(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).delete()
        return Response()

作业

2、 fbv写—》写个装饰器,装饰在视图函数,只要一装饰,以后的request就可以使用request.data,这个data无论是那种编码格式,都有数据


#装饰器
def re_by(func):
    def inner(*args):
        request=args[1]
        import json
        try:
            request.data = json.loads(request.body)
            res=func(*args)
            return res
        except Exception:
            request.data = request.POST
            return func(*args)
    return innerr

class BookView(View):
    def get(self, request):
        book_list = Book.objects.all()
        # queryset 对象 不能直接序列化 只能通过 for循环 一个个拼成列表套字典
        data_list = []
        for book in book_list:
            data_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return JsonResponse(data_list, safe=False, json_dumps_params={'ensure_ascii': False})
    @re_by
    def post(self, request):
        res = request.data
        print(res)
        return HttpResponse('成功')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值