源码剖析Django REST framework的认证方式及自定义认证

源码剖析ref="/15473.html">Django REST framework的认证方式

ref="/15473.html">Django的CBV模式流程,可以知道在url匹配完成后,会执行自定义的类中的as_view方法。

如果自定义的类中没有定义as_view方法,根据面向对象中类的继承可以知道,则会执行其父类View中的as_view方法

在Django的View的as_view方法中,又会调用dispatch方法。

现在来看看Django restframework的认证流程

Django restframework是基于Django的框架,所以基于CBV的模式也会执行自定义的类中的as_view方法

先新建一个项目,配置url

from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^user/', views.UserView.as_view()), ]

views.py文件内容

from django.shortcuts import render,HttpResponse from rest_framework.views import APIView class UserView(APIView): def get(self,request,*args,**kwargs): print(request.__dict__) print(request.user) return HttpResponse("UserView GET") def post(self,request,*args,**kwargs): return HttpResponse("UserView POST")

启动项目,用浏览器向:8000/user/发送get请求

源码剖析Django REST framework的认证方式及自定义认证

可以知道请求发送成功。现在来看看源码流程,由于UserView继承APIView,查看APIView中的as_view方法

class APIView(View): ... @classmethod def as_view(cls, **initkwargs): if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet): def force_evaluation(): raise RuntimeError( 'Do not evaluate the `.queryset` attribute directly, ' 'as the result will be cached and reused between requests. ' 'Use `.all()` or call `.get_queryset()` instead.' ) cls.queryset._fetch_all = force_evaluation view = super(APIView, cls).as_view(**initkwargs) view.cls = cls view.initkwargs = initkwargs return csrf_exempt(view)

通过super来执行APIView的父类Django的View中的as_view方法。上一篇文章源码解析Django CBV的本质中已经知道,View类的as_view方法会调用dispatch方法。

View类的as_view方法源码如下所示

class View(object): ... @classonlymethod def as_view(cls, **initkwargs): ... def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) ...

as_view方法中的self实际上指的是自定义的UserView这个类,上面的代码会执行UserView类中dispatch方法。

由于UserView类中并没有定义dispatch方法,而UserView类继承自Django restframework的APIView类,所以会执行APIView类中的dispatch方法

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) 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

可以看到,先执行initialize_request方法处理浏览器发送的request请求。

来看看initialize_request方法的源码

def initialize_request(self, request, *args, **kwargs): """ Returns the initial request object. """ parser_context = self.get_parser_context(request) return Request( request, parsers=self.get_parsers(), authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context )

在initialize_request方法里,把浏览器发送的request和restframework的处理器,认证,选择器等对象列表作为参数实例化Request类中得到新的request对象并返回,其中跟认证相关的对象就是authenticators。

def get_authenticators(self): """ Instantiates and returns the list of authenticators that this view can use. """ return [auth() for auth in self.authentication_classes]

get_authenticators方法通过列表生成式得到一个列表,列表中包含认证类实例化后的对象

在这里,authentication_classes来自于api_settings的配置

authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES

通过查看api_settings的源码可以知道,可以在项目的settings.py文件中进行认证相关的配置

api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) def reload_api_settings(*args, **kwargs): setting = kwargs['setting'] if setting == 'REST_FRAMEWORK': api_settings.reload()

Django restframework通过initialize_request方法对原始的request进行一些封装后实例化得到新的request对象

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwssg.html