首页 > 其他分享 >drf之APIView

drf之APIView

时间:2022-09-26 19:02:06浏览次数:50  
标签:APIView self request instance 序列化 data drf


一、APIView的基本使用

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

# 现在通过一个继承View和继承APIView来写一个获取所有的图书的接口

View

class BookView(View):
    def get(self, request):
        print(type(request))
        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False})   # 在使用JsonResponse序列化出去

APIView

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

# 要加上drf的Response写这个接口
class BookView(APIView):  # APIView继承自django的View 其实两个是一个View
    def get(self, request):
        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(res_list)  # Response可以直接序列化列表和字符串

二、APIView源码分析

# 首先APIView的路由也是按照下方这样写的
    path('books/', views.Books.as_view())

'''然后我们可以点击as_view查看源码 
然后因为我们自己写的试图类是没有这个方法的
所以我们要去继承的父类查找 那就是APIView '''
# APIView中是有as_view的方法的所以不用再去其他地方查找了
def as_view(cls, **initkwargs):
    # as_view中有调用了父类(View)的as_view方法
    view = super().as_view(**initkwargs)
    # 然后返回了一个csrf装饰器 这样之后只要继承了APIView就可以不用在担心csrf校验了        
    return csrf_exempt(view)

# 然后当路由匹配成功之后 因为APIView的as_view方法又调用了父类(View)的as_view方法 所以会执行View的as_view方法 而父类的as_view我们之前已经知道了其实就是返回了一个self.dispatch 方法
    # 父类(View)的as_view
    def as_view(cls, **initkwargs):
        return self.dispatch(request, *args, **kwargs) # 这个self就是类本身  就是我们自己写的视图类

根据查找顺序当中途遇到一个方法的时候都是从最开始的本身开始查找然后在从父类查找..

所以我们就要再去我们自己写的试图类查找dispatch方法 没有 就要去APIView方法查找

def dispatch(self, request, *args, **kwargs):  # 这个request是django原生的request的
    # 然后initialize_request方法返回的是一个Request对象  所以接下来的request都是drf提供的Request的对象了
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request  
    # 因为是视图类当做参数传入的 所以self就是我们自己写的视图类 就会变成了 视图类对象.request=request 新的request
    # 就是将我们试图类的request也变成了Request的对象

    try:
        # 然后这里执行了三大认证: 认证、权限、频率
        self.initial(request, *args, **kwargs)
        # 这里跟View里一样 都是判断请求来的时候 存不存在
        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  # handler就是如果请求是get那么就是get
        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
def initialize_request(self, request, *args, **kwargs):
    # 就是把传进来的request 变成drf提供的Request类的对象
    return Request(  # 返回Request的实例化对象
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )

1.总结

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

2.验证

#1  视图类中使用的request对象,已经变成了drf提供的Request类的对象了
# 我们可以在继承View的类中打印request的类型看一下
class BookView(View):
    def get(self, request):
        print(type(request))  # django.core.handlers.wsgi.WSGIRequest  这是原生django的request

# 然后在继承APIView的类中打印request的类型
class BookView(APIView): 
    def get(self, request):
        print(type(request))  # rest_framework.request.Request

# 2.request已经不是原来的request了,还能像之前的方法一样用吗?
    还是可以像之前的方法一样用
class BookView(APIView): 
    def get(self, request):
        print(request.method)  #  get
        print(reuqest.path)   # 路径
        print(request.GET)  # 原来的get参数
        print(reuqest.POST)  # 原来的post参数
# 向上面的参数还是能够使用 还是像之前一样的用法

三、Request类的源码分析

# 我们先要研究Request类的源码 rest_framework.request.Request 
的入口其实就是导入这个模块就可以点击去查看 from rest_framework.request import Request

# 在这个类实例化对象的时候 self._request = request 把原生django的request赋值给了self._request了

'''1.然后这个Request类中也有一个魔法方法__getattr__'''
# 这个魔法方法只要 对象.属性 属性不存在的时候就会触发它的执行

    def __getattr__(self, attr):  # 如果取的属性不存在就会去原生django的request对象查找
        try:
            return getattr(self._request, attr)  # 然后通过该反射去原生django的request中查找  
        except AttributeError:
            return self.__getattribute__(attr)
# 所以以后用所有的属性和方法 直接用即可(因为通过反射会去原生django的request中取)

'''2.该类中还有一个data方法'''
该方法被property装饰了,变成了数据属性使用
'''
以后body体中的数据都从这里取  之前是从request.POST中取
urlencoded,form-data:提交的数据在request.POST中
json格式提交的数据,在requets.POST中没有,它在request.body中
''' 
# 现在无论什么格式都从request.data中取
其他: 取文件还是从request.FILES中取

'''3.该类中还有一个query_params方法'''
    @property
    def query_params(self):
        return self._request.GET
# 该方法也被装饰成了属性  然后返回了_request.GET 
# 所以request.query_params 等同于 request._request.GET或 request.GET

验证

# 原生django的request.POST  只有urlencoded和form-data编码格式可以提交数据 而json格式数据在body体中

# 但是drf中只有data, data可以获取所有的编码格式的数据

# 而文件还是从request.FILES中获取

四、序列化组件简介

# 序列化就是drf提供的一个类, 然后我们继承它,写自己的类

# 可以序列化queryset对象或单个对象

# 就是当我们写好后端数据要返回给前端需要序列化才能给前端 所以drf给我们提供了一个类

# 我们之前写的获取所有图书的接口
    -之前我们写的时候需要for循环,然后使用列表套字典的形式序列化给前端

# 现在有一个能够快速实现序列化的类:序列化类

五、序列化组件的使用

5.1 定义序列化类

# 首先我们可以在app下创建一个py文件在该py文件下写我们的序列化组件

from rest_framework import serializers
class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()
# 哪个需要序列化就把哪个的字段给写上即可

5.2 在视图类中使用 序列化多条数据

# 查询全部书籍
class Books(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        # instance 表示需要序列化的数据  many=True表示序列化多条(instance是queryset对象 如果要序列化多条数据 一定要传many=True)
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)

5.3序列化单条数据

# 查询某个书籍
class BooksDetail(APIView):
    def get(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).first()
        # instance还是放需要序列化的数据  如果是单条数据 不用传many=True
        ser = BookSerializer(instance=book_obj)
        return Response(ser.data)

六、反序列化(新增和修改)

# 新增和修改都是前端传进来的数据 需要反序列化和校验 而序列化类中有检验功能

6.1 新增

视图类

class Books(APIView):
    def post(self, request):
       # 从前端传过来的数据 要从request.data中提取
        ser = BookSerializer(request.data)  # 反序列化
        if ser.is_valid():  # 这里就是判断传过来的数据需要校验 不过我们没有写数据校验 所以相当于没有校验
            ser.save()  # 这里如果直接写的话会报错 要重写create方法
            return Response(ser.data)
        else:
            return Response(ser.errors)

# 源码
def save()
      if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
            assert self.instance is not None, (
                '`update()` did not return an object instance.'
            )
        else:
            self.instance = self.create(validated_data)
            assert self.instance is not None, (
                '`create()` did not return an object instance.'
            )
# 因为源码的save判断了instance是否为空如果为空 那么就调用了create方法
# 而源码的create什么都没写 直接报错
    def create(self, validated_data):
        raise NotImplementedError('`create()` must be implemented.')

# 所以我们要去我们自己写的序列化类中重写create方法

序列化类

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

    def create(self, validated_data):  # 只有上面的校验通过了才会执行 所以validated_data肯定有值
        res = BookSerializer(**validated_data)
        return res  # 还有返回出去

# 因为我们自己写的序列化类重写了create方法 所以在save在调用create方法的时候就会直接执行我们自己写的create方法

6.2 修改

视图类

class BooksDetail(APIView):
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        # 前端传过来的数据是从request.data中取 
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()  # 这里还是会报错 需要重写update方法
            return Response(ser.data)
        else:
            return Response(ser.errors)

# 刚刚源码中 如果instance有值的话save就会调用update方法
# 而源码的update方法也是直接报错什么都没有写
    def update(self, instance, validated_data):
        raise NotImplementedError('`update()` must be implemented.')

# 所以需要去自己写的序列化类重写update方法

序列化类

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()

    def update(self, instance, validated_data):
        # instance 是需要修改的数据对象
        # validated_data 是校验过后的数据
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish = validated_data.get('publish')
        instance.save()
   
# 因为我们自己写的序列化类中写了update方法 所以save再调用update就会从我们自己写的序列化类中使用update方法

 

标签:APIView,self,request,instance,序列化,data,drf
From: https://www.cnblogs.com/stephenwzh/p/16731985.html

相关文章

  • APIView基本使用、源码分析,Requset类源码分析,序列化组件的基本使用,反序列化
    1.APIView基本使用1.1使用View+JsonResponse写classBookView(View):defget(self,request):book_list=Book.objects.all()res_list=[]......
  • drf学习-1
      前后端开发模式在开发Web应用中,有两种应用模式:前后端混合开发和前后端分离:一、前后端混合开发   曾经写过的图书管理系统、BBS项目后端人员需要通过前端写好......
  • django之drf入门
    今日内容前后端开发模式补充知识xml模式 <xml>xxx</xml>json模式 {"name":"xxx"}前端的后台管理模板:x-admin 使用的是layui+juqery前端的后台管理模板:admin-lt......
  • drf
    前后端开发模式API接口接口测试工具restful规范序列化和反序列化drf快速使用cbv源码分析前后端开发模式1.前后端混合2.前后端分离前端的后台管理模板:layui+......
  • 【Django-rest-framework框架】第01回 drf入门规范
    目录1.前后端开发模式1.1前后端混合开发1.2前后端分离1.3流程图1.4前端的后台管理模板2.API接口2.1本质2.2四大特点2.3模拟3.接口测试工具postman4.RESTfulAPI......
  • API接口与drf规范
    前后端开发模式1.前后端混合前端写好静态html页面,后端使用模板语法进行渲染,然后在在对接,遇到问题返回给前端进行修改,这要求后端人员会一些HTML、JS等前端语言,这种模式让......
  • drf(djangorestframewor)-01
    目录前后端开发模式API接口接口测试工具postmanrestful规范序列化和反序列化djangorestframework快速使用cbv源码分析前后端开发模式1.前后端结合模式----全栈后端人......
  • 今日内容 API接口和drf的使用
    前后端开发模式详细见博客链接:https://www.cnblogs.com/liuqingzheng/p/10900502.html补充:前后端混合开发使用模板语法渲染模板后端人员要通过前端写好的html页面......
  • 【2022-09-23】DRF入门到入土(一)
    drf入门规范一、web应用模式web应用模式分为两种,一种是前后端不分离,一种是前后端分离前后端不分离前后端分离二、API接口为了在团队内部形成共识、防止......
  • 前后端分离 drf之一
    API接口前后端分离的开发模式:客户端和服务端采用restfulAPI的交互方式进行交互前后端代码库分离,前端代码可以进行mock测试能够独立开发和测试后端则用postman接口测......