【三】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复杂功能的简单场景。
-
仅支持JSON:
JsonResponse
仅支持返回JSON格式的响应,不像DRF的Response
类那样支持多种媒体类型。 -
状态码和头信息:也可以使用
JsonResponse
来设置HTTP状态码和头信息,但其功能相对有限。 -
数据:将Python对象传递给
JsonResponse
,它会自动将其转换为JSON格式。
-
【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_dictclass 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)知识点复习
- 语法糖
- 详情请见:Python 闭包函数和装饰器_python 闭函数-CSDN博客
- 这两种写法都是一样的效果,在index方法上加了
csrf_exempt
装饰器,取消了验证
@csrf_exempt
def index(request):passindex=csrf_exempt(index)
(1)首先确定继承关系
- 自定义了
BookAPIView
的视图函数 BookAPIView
的视图函数继承了drf的APIView
- 通过看源码,发现
APIView
继承了View
- 那么这个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)重点部分分析
- 首先通过路由层的路由匹配,找到视图函数并执行
- 这里将执行
TBookAPIView.as_view()(request)
这个方法 - 自动加括号并将参数request参数传递进去
- 这里将执行
- 查找as_view方法
- 根据之前确定的继承关系,知道了查找顺序,首先去
TBookAPIView
中找,显然是没有的 - 然后去
APIView
中找,很快就找到了,但是他又执行了super().as_view(**initkwargs)
- 所以最终去View中找,之前分析CBV源码的时候已经知道了
- 这里提前说一下最后的结果,
csrf_exempt(view)
,这个用csrf_exempt
装饰器,只不过没有用语法糖装饰 - 所以基于APIView书写的CBV是没有csrf验证的
- 根据之前确定的继承关系,知道了查找顺序,首先去
- 执行View的as_views方法
- 这里是一个闭包函数,所以到这里的将执行的内容为,在返回的view后面加上括号和request参数
view(request, *args, **kwargs)
,接下来执行dispath
方法,又开始寻找这个方法了 - 首先去
TBookAPIView
中找,显然是没有的 - 然后去
APIView
中找,很快就找到了,所以接下来执行APIView
的dispatch
方法
- 这里是一个闭包函数,所以到这里的将执行的内容为,在返回的view后面加上括号和request参数
- 执行
APIView
的dispatch
方法- 首先执行了
initialize_request
方法,同理去找这个方法,最终在APIView
的中找到 - 执行
initialize_request
方法- 这里不做过多叙述,后面会详细讲解
- 简单来说就是在Django的request的外面包装了一层,将原本的request方法保留,并在其方法上加了一些其他很好用的方法和属性
- 接下来执行initial方法,同理有要按照顺序去找这个方法,最终还是在
APIView
的中找到- 这个方法内部一次执行了用户、权限、频率的验证,这里目前也不做过多赘述
- 首先执行了
- 最后和View的处理方法一样
- 这里执行了反射方法
getattr
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
- 第一个参数
self
还是TaskView
的实例 - 第二个参数是当前请求方式的小写方法,这个例子中是
get
字符串 - 第三个参数就是没有找到将会返回的数据,这个不是重点不用管
- 第一个参数
- 通过反射就拿到了我们定义在
TaskView
的实例中的get方法,执行get方法即可,get(self, request, *args, **kwargs)
- 这里执行了反射方法
(3)APIView小结
- APIView不用csrf验证了
- APIView的request方法不在是以前的request方法,有了很多好用的新方法
- APIView内部还分别进行了了用户、权限、频率的验证