DRF APIView源码分析

本文分析了DjangoRESTframework中的Response和JsonResponse的区别,以及如何在APIView中实现基本操作,包括内容类型协商、数据序列化和视图层的使用。着重讲解了APIView的源码结构,包括继承关系、视图处理流程和验证机制。
摘要由CSDN通过智能技术生成

【三】APIView源码分析

【1】Response和JsonResponse的区别

(1)Django REST framework的Response

  • DRF的Response类是专门为构建RESTful API设计的。

  • 它不仅仅是一个简单的JSON响应,而是包含了一系列与RESTful API交互有关的功能。

    • 内容类型协商:DRF的Response类能够自动处理内容类型协商,根据客户端的请求头(如Accept)来返回适当的媒体类型。

    • 渲染器:DRF提供了多种渲染器,可以将响应数据渲染为不同的格式(如JSON、XML等)。Response类会根据请求的内容类型选择适当的渲染器。

    • 状态码:DRF的Response类可以轻松设置HTTP状态码,以表示API请求的成功或失败。

    • 头信息:可以使用Response类来设置HTTP响应的头信息。

    • 数据序列化:DRF的序列化器与Response类紧密集成,使得从数据库模型到JSON响应的转换变得简单。

(2)Django的JsonResponse

  • Django的JsonResponse是一个简单的类,用于返回JSON格式的HTTP响应。

  • 它主要用于那些不需要DRF复杂功能的简单场景。

    • 仅支持JSONJsonResponse仅支持返回JSON格式的响应,不像DRF的Response类那样支持多种媒体类型。

    • 状态码和头信息:也可以使用JsonResponse来设置HTTP状态码和头信息,但其功能相对有限。

    • 数据:将Python对象传递给JsonResponse,它会自动将其转换为JSON格式。

image-20240412194413961

【2】简单使用APIView

  • 视图层
    • 这个基于APIView编写的CBV视图和基于View的CBV视图目前来看是没有区别的
from rest_framework.views import APIView
from book.models import Book
from rest_framework.response import Response
from django.forms.models import model_to_dict


class BookAPIView(APIView):
    def get(self, request, *args, **kwargs):
        book_queryset = Book.objects.all()
        results = [model_to_dict(info_fict) for info_fict in book_queryset]
        return Response({'code': 100, 'msg': '查询成功', 'results': results})
  • 补充:model_to_dict:这个方法可以快速将模型表的obj转换成dict

【3】APIView源码解析

(0)知识点复习

@csrf_exempt
def index(request):
    pass
    
index=csrf_exempt(index)    

(1)首先确定继承关系

  1. 自定义了BookAPIView的视图函数
  2. BookAPIView的视图函数继承了drf的APIView
  3. 通过看源码,发现APIView继承了View
  4. 那么这个View是Django的CBV视图中的View吗?
    • 是的,打印一下这两个View,可以发现是一个View
    • 所以继承APIView后任可以按照普通的View书写
from rest_framework.views import APIView
from django.views import View
print(issubclass(APIView, View))  # True
  • 所以继承关系为:
    • BookAPIView --> APIView --> View
    • 所以源码的分析中无论是属性还是方法,都是按照这个继承顺序来查找

(2)重点部分分析

  1. 首先通过路由层的路由匹配,找到视图函数并执行
    • 这里将执行TBookAPIView.as_view()(request)这个方法
    • 自动加括号并将参数request参数传递进去
  2. 查找as_view方法
    • 根据之前确定的继承关系,知道了查找顺序,首先去TBookAPIView中找,显然是没有的
    • 然后去APIView中找,很快就找到了,但是他又执行了super().as_view(**initkwargs)
    • 所以最终去View中找,之前分析CBV源码的时候已经知道了
    • 这里提前说一下最后的结果,csrf_exempt(view),这个用csrf_exempt装饰器,只不过没有用语法糖装饰
    • 所以基于APIView书写的CBV是没有csrf验证的
  3. 执行View的as_views方法
    • 这里是一个闭包函数,所以到这里的将执行的内容为,在返回的view后面加上括号和request参数view(request, *args, **kwargs),接下来执行dispath方法,又开始寻找这个方法了
    • 首先去TBookAPIView中找,显然是没有的
    • 然后去APIView中找,很快就找到了,所以接下来执行APIViewdispatch方法
  4. 执行APIViewdispatch方法
    • 首先执行了initialize_request方法,同理去找这个方法,最终在APIView的中找到
    • 执行initialize_request方法
      • 这里不做过多叙述,后面会详细讲解
      • 简单来说就是在Django的request的外面包装了一层,将原本的request方法保留,并在其方法上加了一些其他很好用的方法和属性
    • 接下来执行initial方法,同理有要按照顺序去找这个方法,最终还是在APIView的中找到
      • 这个方法内部一次执行了用户、权限、频率的验证,这里目前也不做过多赘述
  5. 最后和View的处理方法一样
    • 这里执行了反射方法getattr
    • handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
      • 第一个参数self还是TaskView的实例
      • 第二个参数是当前请求方式的小写方法,这个例子中是get字符串
      • 第三个参数就是没有找到将会返回的数据,这个不是重点不用管
    • 通过反射就拿到了我们定义在TaskView的实例中的get方法,执行get方法即可,get(self, request, *args, **kwargs)

image-20240412212643352

(3)APIView小结

  • APIView不用csrf验证了
  • APIView的request方法不在是以前的request方法,有了很多好用的新方法
  • APIView内部还分别进行了了用户、权限、频率的验证

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值