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)