首页 > 编程语言 >DRF请求的生命周期:三年程序员的实战感悟

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

时间:2024-10-01 10:46:15浏览次数:7  
标签:感悟 self args request 程序员 kwargs DRF response view

前言:作为工作一个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 response
2、再执行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 view

3、通过路由匹配执行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.response
4、在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方法并返回数据到客户端

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

标签:感悟,self,args,request,程序员,kwargs,DRF,response,view
From: https://www.cnblogs.com/harry6/p/18438720

相关文章

  • DRF实操——项目部署
    DRF实操——项目部署一、Mysql集群1.集群方式1)Replication集群2)PXC集群2.Docker安装PXC知识补充:具名数据卷创建docker容器django后端接口服务二、Nginx概述作用安装配置三、uWSGI1.概述2.项目的配置3.将本地项目及环境打包到服......
  • 一个程序员炒股后的心酸历程
        我今年四十多岁,在世纪初拿到了一个不入流的本科学历。毕业那年,仍心有不甘,尝试参加了当年全国研究生统一考试,虽然初试成绩有361分,是当年所报考学校所报考学院的第四名,但仍在复试中以微弱劣势,低于0.5分的综合成绩在三十二名选手中惨糟淘汰。值得炫耀的是,这次研究生......
  • 程序员世界大冒险d22
    今天上了Java课,老师让生成对话框,不怎么会,该学学的,下面是代码:importjava.util.Random;importjavax.swing.;importjava.awt.;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;classMethod{publicString[][]generateQuestions(){Randomran......
  • 分享C++程序员面试八股文(十五)
    以下是C++常见八股文(十五):一、C++中的高级文件操作(AdvancedFileOperations)解释文件随机访问的方法及应用场景方法:在C++中,可以使用文件流对象(如std::ifstream、std::ofstream、std::fstream)的seekg(设置输入位置)和seekp(设置输出位置)成员函数来实现文件的随机访问。这......
  • 分享C++程序员面试八股文(十四)
    以下是C++常见八股文(十四):一、C++中的智能指针高级用法(AdvancedUsageofSmartPointers)解释unique_ptr、shared_ptr和weak_ptr的循环引用问题及解决方法循环引用问题:当使用shared_ptr进行相互引用时,可能会导致循环引用问题。例如,两个对象相互持有对方的shared_pt......
  • 行业机遇!程序员:如何选择适合自己的就业方向?
    随着科技的不断进步和发展,程序员的就业前景也越来越广阔。而在这个快速发展的行业中,在各个领域都有着广泛的应用,信息技术的迅猛发展使得程序员在现代社会中占据了举足轻重的地位。从软件开发到网络安全,再到人工智能,程序员的就业机会广泛且前景光明,为程序员提供了丰富多彩的职......
  • 数据库离程序员有多远 - cnblogs救园行动感想
    这两周,我参与了博客园的“2024救园行动”,成了终身会员。说实话,当初报名的时候,我心里还挺兴奋的,想着这下能和不少老朋友在这个社区里再次相聚。毕竟,在数据库行业摸爬滚打了这么多年,自认为也认识不少圈内人士,更不用说程序员群体了。可结果却有点出乎意料。当我翻看那500位终身会员的......
  • 未来的程序员的自我介绍
    自我介绍大家好,非常高兴能在这里与你们分享我的编程学习旅程。在这个数字化日益发展的时代,我认为掌握编程技能不仅是一项实用的能力,也是通往未来世界的一把钥匙。通过这些博客,我希望记录下自己的成长历程,同时也希望能够得到大家的支持和建议。编程的目标作为一名普通的双......
  • 分享C++程序员面试八股文(十三)
    以下是C++常见八股文(十三):一、C++中的命名空间和模块的高级用法(AdvancedUsageofNamespacesandModules)解释命名空间别名和嵌套命名空间的作用及使用场景命名空间别名:作用:命名空间别名可以为一个较长或复杂的命名空间提供一个更简洁的名称,提高代码的可读性和可......
  • 【转型必看】Java到AI大模型,程序员的逆袭秘籍,转行不再是梦!
    随着技术的不断进步,人工智能(AI)大模型已经成为当今科技领域最热门的话题之一。许多开发者开始考虑从传统的软件开发领域,如Java,转向人工智能领域,今天小编和大家一起来探讨Java开发者是否可以转型到人工智能大模型,转型的优势,薪资对比,以及转型所需的知识和学习路线等。01Java......