继承APIView后as_view发生了什么变化
APIview也是继承了View方法,也就是说API不仅可以调用View的方法和属性,还在APIView的基础上增加了新的功能。
views.py
from rest_framework.views import APIView # Create your views here. class Index(APIView): def get(self,request,): pass def post(self,request): pass # 分析: # 我们学习认证组件的时候是基于restframework的,所以我们这里继承APIView,这个View有什么差别在哪呢?
urls.py里的写法和继承View一样,用的是as_view方法
API的 as_view()方法
@classmethod def as_view(cls, **initkwargs): if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet): def force_evaluation(): raise RuntimeError( ... ) cls.queryset._fetch_all = force_evaluation view = super().as_view(**initkwargs) view.cls = cls view.initkwargs = initkwargs # Note: session based authentication is explicitly CSRF validated, # all other authentication is CSRF exempt. return csrf_exempt(view) # 分析: # API 是继承了父类的as_view()方法,那么我们直接找dispatch,API类自己写的dispatch方法
APIView的dispatch方法
def dispatch(self, request, *args, **kwargs): self.args = args - self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request # 分析: # 我们看到这里的request是进行处理的,赋值给新的request,已经不是原生的request了 # 下面由对request = self.initialize_request(request, *args, **kwargs)的分析,可以先看下面对此方法的分析,分析结果内部实例化了个Request的类,原生request可用request._request的方法获得。 self.headers = self.default_response_headers # deprecate? try: self.initial(request, *args, **kwargs) # 分析: # 下面由initial的分析方法,就是调用方法之前运行任何需要发生的操作 # Get the appropriate handler method 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 # 分析: # 这里的写法和view里的写法是一样了,判断方法在不在http_method_names里,如果在就执行,不在抛异常,但是注意的是APIView里的method传入的request已经是加工后的了,想要原生的request需要request._request。
request = self.initialize_request(request, args, *kwargs) 分析
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 ) # 分析: # 返回了一个Request实例化的对象,其中有request和authenticators方法,那么新的request也就可以点出这些方法。 # 这里的Request方法是从request.py中导入的 from rest_framework.request import Request def __init__(self, request, parsers=None, authenticators=None, negotiator=None, parser_context=None): self._request = request self.authenticators = authenticators or () # 分析: # 将原生的request赋值给属性_request,如果在类里面想用原生的request,那就得 request._request。 # 还有这里的authenticators,上面实例化时传入了值authenticators=self.get_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] # 分析: # 得到的是一个列表,列表里实例化并返回此试图可以使用的验证器列表。
initial方法分析
def initial(self, request, *args, **kwargs): """ Runs anything that needs to occur prior to calling the method handler. """ self.format_kwarg = self.get_format_suffix(**kwargs) # Ensure that the incoming request is permitted self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request) # 在调用方法之前运行任何需要发生的操作,我们看到self.perform_authentication(request) def perform_authentication(self, request): """ Perform authentication on the incoming request. Note that if you override this and simply 'pass', then authentication will instead be performed lazily, the first time either `request.user` or `request.auth` is accessed. """ request.user # 分析 request已经是加工之后的request了,所以我们去request.py里找有没有user方法 @property def user(self): if not hasattr(self, '_user'): with wrap_attributeerrors(): self._authenticate() return self._user # 分析: # 验证成功后返回通过验证的用户,可以通过下面的方法获得 @user.setter def user(self, value): self._user = value self._request.user = value