Django rest-framework 用户登录认证源码剖析
Django 是一个开放源代码的 Web 应用框架,由Python写成。作为 Python 最热门的后台框架之一,Django 平台上也涌现了很多优秀的基于它开发的框架。而 Django rest-framework,则是其中最为流行的框架。大家都知道它基于 Django 实现的一个 RESTful 风格 API 框架,能够帮助我们快速开发RESTful风格的API。但其实他不仅仅如此描述的这般单一,本篇文章主要从源码的角度剖析 Django rest-framework 的用户登录认证流程以及如何全局以及定制化认证。本篇主要基于 CBV 进行用例展示。
源码版本: 3.1.7
Python 版本:3.9.1
CBV
当来自前端的请求通过网络到达 Django 服务时,通过 Django 的路由系统,在 CBV 下通常会定位到一个 View class:
urlpatterns = [
url(r'test.html$', TestDemo.as_view())
]
定义一个最简单的视图类 TestDemo:
class TestDemo(APIView):
def get(self, request):
return JsonResponse({
})
这里有一个问题: CBV 到底是如何做到直接可以不用显式地判断 request.method
就可以自动调用视图类中的对应方法的呢?
其实这里使用了Python 反射的技巧。as_view 会导致 TestDemo 在执行到用户 view 之前调用 view.dispatch 方法。dispatch 方法如下:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):
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
return handler(request, *args, **kwargs)
通过获取到 request.method
后在视图类中利用反射,将 TestDemo 中的 get 方法赋值给 handler,然后执行 get函数
getattr(self, …) 中 self 是 TestDemo 的对象。handle 是指向 TestDemo 中 get 函数对象的变量,所以handle也是 callable。
讲到这里总结一下:
CBV 通过 dispatch 进行方法的派发,自动通过方法名调用对应方法。
APIView VS View
当然今天的主人公是 Django rest-framework,那我们就得看一下 APIView 类的内容与 View 有什么不同。老规矩先读源码:
class APIView(View):
...
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs)
# =====================================