核动力 发表于 2024-10-1 13:26:50

DRF请求的生命周期:三年程序员的实战感悟

前言:作为工作一个3年左右的码农,在各种框架的摸爬滚打中,我也接触了不少前端后端的技术栈,其中 Django REST Framework(DRF)算是我后端日常工作中的用得最多的框架。今天就简单聊聊DRF请求的生命周期。从请求的发起,到数据的处理,再到最终的响应返回,每一步都有着很多的细节和挑战,由于篇幅原因,我在此篇文章中只是稍作解析,点到为止。
drf中请求的生命周期:

1、django接收请求后,先进行中间件的process_request方法,进行路由匹配后再进行中间件的process_view方法;

class MiddlewareMixin:
        # 中间件源码,当有请求进来时,会自动执行中间件的call方法;
        # 一般我们自定义中间件都是重写process_request和process_view方法
        # 从源码中可看出执行顺序:
    def __call__(self, request):
      # Exit out to async mode, if needed
      if asyncio.iscoroutinefunction(self.get_response):
            return self.__acall__(request)
      response = None
      if hasattr(self, 'process_request'):
            response = self.process_request(request)   
      response = response or self.get_response(request)
      if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
      return response2、再执行APIView类中的as_view方法获取view函数,并同时免除了csrf认证(闭包原理)

class APIView(View):
    # 简略版源码:
    @classmethod
    def as_view(cls, **initkwargs):
      view = super().as_view(**initkwargs) # 调用原Django框架的as_view方法获取view函数
      view.cls = cls
      view.initkwargs = initkwargs
      return csrf_exempt(view)

# 原Django框架的as_view方法:
class View:
    @classonlymethod
    def as_view(cls, **initkwargs):
      def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.setup(request, *args, **kwargs)
            return self.dispatch(request, *args, **kwargs) # 调用dispatch函数
      view.view_class = cls
      view.view_initkwargs = initkwargs
      return view3、通过路由匹配执行view函数,并在view中调用dispatch函数。

class APIView(View):
    def dispatch(self, request, *args, **kwargs):
      self.args = args
      self.kwargs = kwargs
        # request封装
      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.response4、在dispatch中进行版本管理、request封装、认证、权限、限流处理

# 版本管理
    def initial(self, request, *args, **kwargs):

      self.format_kwarg = self.get_format_suffix(**kwargs)

      version, scheme = self.determine_version(request, *args, **kwargs)# 执行versioning_class中的determine_version方法,获取version和scheme
      request.version, request.versioning_scheme = version, scheme# 封装参数到request中

      # Ensure that the incoming request is permitted
      self.perform_authentication(request)
      self.check_permissions(request)
      self.check_throttles(request)


# request封装
    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 _authenticate(self):
      for authenticator in self.authenticators:
            try:
                user_auth_tuple = authenticator.authenticate(self) # 执行authenticate方法进行具体的认证流程
            except exceptions.APIException:
                self._not_authenticated()
                raise

            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple# 将返回值进行封装
                return

      self._not_authenticated()


# 权限
    def check_permissions(self, request):
      for permission in self.get_permissions():
            if not permission.has_permission(request, self):# 多个权限类中有一个方法为False则报错并抛出异常
                self.permission_denied(
                  request,
                  message=getattr(permission, 'message', None),
                  code=getattr(permission, 'code', None)
                )


# 限流
    def check_throttles(self, request):
      throttle_durations = []
      for throttle in self.get_throttles(): # 循环执行各限流类中的方法
            if not throttle.allow_request(request, self):
                throttle_durations.append(throttle.wait()) # 限流方法返回False则将等待时间加到列表中

      if throttle_durations:
            durations = [
                duration for duration in throttle_durations
                if duration is not None
            ]

            duration = max(durations, default=None) # 取列表中的最大等待时间
            self.throttled(request, duration)# 抛出异常5、执行具体的视图函数并返回数据

6、执行中间件的process_response方法并返回数据到客户端

以上只是简单分析了一下执行流程,涉及到的源码都是为了方便理解而经过简化的,只供参考。每个组件源码的设计思路和执行流程其实都有一定的复杂度,对于各个组件的源码,我在接下来的日子中也会逐一进行详细剖析。

来源:https://www.cnblogs.com/harry6/p/18438720
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: DRF请求的生命周期:三年程序员的实战感悟