APIView分析

APIView源码分析

from rest_framework.views import APIView

class BookAPIView(APIView):
    ...
    
入口 urlpatterns = [
    url(r'^books/(\d*)', views.BookAPIView.as_view()),
] as_view()


@classmethod   # 类的绑定方法
def as_view(cls, **initkwargs):

    ...

    view = super().as_view(**initkwargs) # 调用父类(View)中的as_view方法(也就是CBV中源码中的as_view方法)
    view.cls = cls
    view.initkwargs = initkwargs
    # 取消csrf认证(csrf装饰器)
    return csrf_exempt(view) # 相当于 return view
# 当请求过来---》路由匹配上---》执行view(request)


def view(request, *args, **kwargs):
    self = cls(**initkwargs) # 调用类的类名,这里就是BookAPIView,实列化对象。
    ...

    self.request = request
    self.args = args
    self.kwargs = kwargs
    return self.dispatch(request, *args, **kwargs)
    # 注意: 这里的self是BookAPIView实列化的对象,BookAPIView继承了APIView,所以这里调用的是APIView里的dispatch方法


def dispatch(self, request, *args, **kwargs):
    self.args = args
    self.kwargs = kwargs
    # 这里重新包装request对象
    request = self.initialize_request(request, *args, **kwargs)
    # 重新包装完request对象然后再复值给request
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

    try:
        # 三大认证模块
        self.initial(request, *args, **kwargs)
        
        # 判断请求方法是否在http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']中
        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


def initialize_request(self, request, *args, **kwargs):

    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
    )


def initial(self, request, *args, **kwargs):
    self.format_kwarg = self.get_format_suffix(**kwargs)

    neg = self.perform_content_negotiation(request)
    request.accepted_renderer, request.accepted_media_type = neg

    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme

    # 认证组件:校验用户 - 游客、合法用户、非法用户
    # 游客:代表校验通过,直接进入下一步校验(权限校验)
    # 合法用户:代表校验通过,将用户存储在request.user中,再进入下一步校验(权限校验)
    # 非法用户:代表校验失败,抛出异常,返回403权限异常结果
    self.perform_authentication(request)

    # 权限组件:校验用户权限 - 必须登录、所有用户、登录读写游客只读、自定义用户角色
    # 认证通过:可以进入下一步校验(频率认证)
    # 认证失败:抛出异常,返回403权限异常结果
    self.check_permissions(request)

    # 频率组件:限制视图接口被访问的频率次数 - 限制的条件(IP、id、唯一键)、频率周期时间(s、m、h)、频率的次数(3/s)
    # 没有达到限次:正常访问接口
    # 达到限次:限制时间内不能访问,限制时间达到后,可以重新访问
    self.check_throttles(request)

猜你喜欢

转载自www.cnblogs.com/chenwenyin/p/13405552.html