Djanog的中间件

1 中间件的五个方法

  • process_request(self,request)
  • process_response(self, request, response)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_exception(self, request, exception)
  • process_template_response(self,request,response)
中间件处理函数什么时候执行执行顺序返回值
process_request收到请求,未进行路由匹配从顶至低None或者HttpResponse对象
process_response视图执行完毕,返回响应时前从低至顶HttpResponse对象
process_view进行路由匹配完成,执行视图函数之前从顶至低None或者HttpResponse对象
process_exception视图执行中发生异常时从低至顶None或者HttpResponse对象
process_template_response视图刚执行完毕,进入process_response之前从低至顶实现了render方法的响应对象

2 中间件的执行流程

在这里插入图片描述

  1. 路由还未匹配时自顶而下执行中间价中的request

  2. 匹配到路由后还未执行视图函数时,自顶而下执行view函数

  3. 执行视图函数,返回response

  4. 当视图函数返回时,自低而上执行中间件response

如果每层执行过程中出现问题获取拒绝执行,如request中返回Httpresponse或出现异常,会直接跳到exception或respon,不会继续执行request和view。

3 中间件如何使用

  1. 新建一个mideleware的文件夹
  2. 在middleware创建不同功能的middleware.py文件
  3. 在middleware.py文件中根据功能些Middleware类继承MiddlewareMixin
  4. 在setting.py文件中的MIDDLEWARE列表中,添加的样式为middleware文件夹.middleware.py文件.middleware类

在这里插入图片描述

# testMiddleware.py
from django.utils.deprecation import MiddlewareMixin
from django.http.response import JsonResponse


class Middleware1(MiddlewareMixin):

    def process_request(self, request):
        print("Middleware1->process_request")

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("Middleware1->process_view")

    def process_response(self, request, response):
        print("Middleware1->process_response")
        return response

    def process_exception(self, request, exception):
        print("Middleware1->process_exception")

    def process_template_response(self, request, response):
        print("Middleware1->rocess_template_response")
        return responce


class Middleware2(MiddlewareMixin):

    def process_request(self, request):
        print("Middleware2->process_request")

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("Middleware2->process_view")


    def process_response(self, request, response):
        print("Middleware2->process_response")
        return response

    def process_exception(self, request, exception):
        print("Middleware2->process_exception")

    def process_template_response(self, request, response):
        print("Middleware2->rocess_template_response")
		return responce

class Middleware3(MiddlewareMixin):

    def process_request(self, request):
        print("Middleware3->process_request")

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("Middleware3->process_view")

    def process_response(self, request, response):
        print("Middleware3->process_response")
        return response

    def process_exception(self, request, exception):
        print("Middleware3->process_exception")

    def process_template_response(self, request, response):
        print("Middleware3->rocess_template_response")
        return responce
# urls.py
from django.contrib import admin
from django.urls import path
from django.http.response import JsonResponse
from django.shortcuts import HttpResponse


def home(request):
    print("view->home")
    return JsonResponse({"message": "hell world"})


urlpatterns = [
    path('admin/', admin.site.urls),
    path("home/", home, name="home")
]

# setting.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    "middleware.testMiddleware.Middleware1",
    "middleware.testMiddleware.Middleware2",
    "middleware.testMiddleware.Middleware3",
]

访问/home网址,界面打印
在这里插入图片描述

4 中间件执行的各种情况

1 request中被中断, 当中间件中的request中返回了一个httpresponse时,中间件将被中断,不会执行继续执行中间件,直接跳转到对应中间的process_response中执行

在这里插入图片描述

# 中间件2中process_request返回HttpResponce
....
class Middleware2(MiddlewareMixin):

    def process_request(self, request):
        print("Middleware2->process_request")
        return JsonResponse({"message": "middleware"})

    ......

在这里插入图片描述

中间件2中process_request直接返回HttpResponce时,跳过下面中间件和视图函数直接执行中间件2的process_response

2 view中被中断,单view中返回一个httpresponce时,会立即进入response中间中, 跳过其他中间件和视图函数

在这里插入图片描述

# 中间件2返回httpresponce
class Middleware2(MiddlewareMixin):

    .....

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("Middleware2->process_view")
		  return JsonResponse({"message": "middleware"})

   ......

在这里插入图片描述

中间件2的process_view返回了HttpResponce时,跳过下面中间和视图函数直接执行中间件3的process_responce

3 当视图中出现异常时, 会直接跳转到exception中,执行顺序是从低而上

在这里插入图片描述

# 模拟视图出现异常
def home(request):
    1/0
    print("view->home")
    return JsonResponse({"message": "hell world"})

在这里插入图片描述

当视图中的出现异常的话直接跳转到中间件3的process_exception中,如果process_exception中没有处理这个错误这个错误会一直沿着中间返回到前端。

4 当视图中出现异常时, exception 有错误的处理,将跳出exception执行到responce中

在这里插入图片描述

# 模拟异常处理
class Middleware3(MiddlewareMixin):

   ....

    def process_exception(self, request, exception):
        print("Middleware3->process_exception")
        # 模拟异常处理
        return JsonResponse({})

	...

在这里插入图片描述

视图函数中出现异常,异常被中间件3处理就不会执行其他的exception。

5 中间件的实现原理

在Django源码中,中间件的实现原理主要体现在Django的django.core.handlers.base模块中,特别是BaseHandler类和其子类WSGIHandler。Django的请求/响应处理流程中,中间件是通过这些类和它们的方法来管理和调用的。

以下是Django中间件实现原理的源码分析:

  1. 中间件的加载
    在Django启动时,它会从settings.py文件中的MIDDLEWARE设置中加载中间件类,并创建一个中间件实例列表。
  2. 请求处理流程
    当Django接收到一个WSGI请求时,它首先会创建一个WSGIRequest对象来表示这个请求,然后开始处理流程。
  3. 调用中间件的process_request方法
    WSGIHandler类的_get_response方法中,Django会遍历中间件实例列表,并调用每个中间件的process_request方法。如果这个方法返回了一个HttpResponse对象,则处理流程会立即停止,并返回这个响应给客户端。
class MiddlewareMixin:
    sync_capable = True
    async_capable = True

    # RemovedInDjango40Warning: when the deprecation ends, replace with:
    #   def __init__(self, get_response):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super().__init__()

    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

    def _get_response_none_deprecation(self, get_response):
        if get_response is None:
            warnings.warn(
                'Passing None for the middleware get_response argument is '
                'deprecated.',
                RemovedInDjango40Warning, stacklevel=3,
            )

def _get_response(self, request):  
    response = None  
    # Apply request middleware  
    for middleware_method in self._request_middleware:  
       response = middleware_method(request)  
       if response:  
           break

这里的self._request_middleware是一个包含中间件process_request方法的列表。

  1. 执行视图函数
    如果所有中间件的process_request方法都成功执行完毕,Django会调用resolver.resolve404()来获取匹配的视图函数,并执行它。

  2. 调用中间件的process_response方法
    视图函数执行完毕后,Django会开始调用中间件的process_response方法。这些方法是按照与process_request相反的顺序调用的,以确保按照正确的顺序处理响应。

    response = response_middleware(request, response)
    

    WSGIHandler类的_get_response方法中,Django会遍历一个包含process_response方法的中间件列表,并将请求和视图函数返回的响应作为参数传递给每个方法。每个方法都可以修改或替换响应对象。

  3. 返回响应
    最后,经过所有中间件的process_response方法处理后,Django会将最终的HttpResponse对象发送给客户端。

在源码级别,中间件的执行逻辑是嵌套在请求/响应处理流程中的。Django通过维护中间件列表和调用相应的方法,确保请求在到达视图之前和响应在返回客户端之前都能经过中间件的处理。

此外,Django的中间件机制还考虑了一些异常处理和清理工作,以确保即使在中间件或视图函数中发生异常时,也能正确执行清理操作(如关闭数据库连接等)。这些逻辑通常位于BaseHandler类的_get_response方法的异常处理部分。

总体来说,Django的中间件实现原理体现了其请求/响应处理流程的灵活性和可扩展性,允许开发者在关键点上插入自定义逻辑,以实现各种功能需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/553467.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

详解运算符重载,赋值运算符重载,++运算符重载

目录 前言 运算符重载 概念 目的 写法 调用 注意事项 详解注意事项 运算符重载成全局性的弊端 类中隐含的this指针 赋值运算符重载 赋值运算符重载格式 注意点 明晰赋值运算符重载函数的调用 连续赋值 传引用与传值返回 默认赋值运算符重载 前置和后置重载 前…

Scikit-Learn

机器学习中的重要角色 Scikit-Leran(官网:https://scikit-learn.org/stable/),它是一个基于 Python 语言的机器学习算法库。Scikit-Learn 主要用 Python 语言开发,建立在 NumPy、Scipy 与 Matplotlib 之上,…

嵌入式中strstr函数详解

一、strstr函数是什么? strstr函数是 C 语言中的一个标准库函数(使用时要引入头文件string.h),用于在一个字符串中查找另一个字符串首次出现的位置。如果找到子串,则返回子串在主串中首次出现的位置的指针;如果未找到,则返回 NULL。 二、使用场景 1.用来找出字符串1在字…

学习了解大模型的四大缺陷

由中国人工智能学会主办的第十三届吴文俊人工智能科学技术奖颁奖典礼暨2023中国人工智能产业年会于2024年4月14日闭幕。 会上,中国工程院院士、同济大学校长郑庆华认为,大模型已经成为当前人工智能的巅峰,大模型之所以强,是依托了…

GPT国内怎么用

2022年11月,OpenAI发布了ChatGPT,这标志着大型语言模型在自然语言处理领域迈出了巨大的一步。ChatGPT不仅在生成文本方面表现出了惊人的流畅度和连贯性,更为人工智能应用开启了全新的可能性。 ChatGPT的推出促进了人工智能技术在多个领域的广…

网工交换技术基础——VLAN原理

1、VLAN的概念: VLAN(Virtual LAN),翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域。 2、VLAN的主要作用&#xf…

stm32f103c8t6学习笔记(学习B站up江科大自化协)-SPI

SPI通信 SPI,(serial peripheral interface),字面翻译是串行外设接口,是一种通用的数据总线,适用于主控和外挂芯片之间的通信,与IIC应用领域非常相似。 IIC无论是在硬件电路还是在软件时序设计…

JUC知识点三

执行TestFrames这个类的时候发生了什么呢? 执行TestFrames这个类的时候发生了什么呢? 1、首先执行一个类加载,把TestFrames这个类的二进制字节码加载到java虚拟机中的方法区内存中(其实是二进制的字节码,只是为了好理…

linux运行ant 报错 Unable to locate tools.jar【已解决】

linux安装 ant 运行时报错 Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.402.b06-1.el7_9.x86_64/lib/tools.jar 原因 已安装的jdk只有运行环境,没有tool.jar,而ant运行需要java开发环境,因…

如何进行数据库的迁移与同步——【DBA 从入门到实践】第四期

在日常的数据库运维工作中,我们时常会面临数据库替换、机房搬迁、业务测试以及数据库升级等任务,这些任务都需要对数据进行迁移和同步操作。【DBA 从入门到实践】第4期,将引导大家深入了解数据库迁移的流程,并探讨在迁移过程中可用…

Zynq学习笔记--AXI 总线仿真(AXI VIP)

目录 1. 概述 2. Simulation with AXI VIP 2.1 axi_vip_pkg 2.2 design_1_axi_vip_0_0_pkg 2.3 参数指定 3. 实例化注意事项 3.1 名称对应关系 3.2 寄存器地址 3.3 block design 1. 概述 AXI Verification IP(AXI VIP)是一种用于验证AXI总线协议的…

无需公网IP,安全稳定实现U8C异地访问

无需公网IP,安全稳定实现U8C异地访问 用友是全球领先的企业云服务与软件提供商, 在财务、人力、供应链、采购、制造、营销、研发、项目、资产、协同等领域为客户提供数字化、智能化、社会化的企业云服务产品与解决方案。 U8C是用友针对成长型、创新型…

ElasticSearch中使用向量和关键词联合检索

注:案例测试数据及其索引构建详见:ElasticSearch中使用bge-large-zh-v1.5进行向量检索(一)-CSDN博客 中的第三部分。 假设任务场景为:用“新疆”向量检索相关的数据,同时需要匹配关键词“巴州”。 首先获取…

最新免费 ChatGPT、GPTs、AI换脸(Suno-AI音乐生成大模型)

🔥博客主页:只恨天高 ❤️感谢大家点赞👍收藏⭐评论✍️ ChatGPT3.5、GPT4.0、GPTs、AI绘画相信对大家应该不感到陌生吧?简单来说,GPT-4技术比之前的GPT-3.5相对来说更加智能,会根据用户的要求生成多种内容…

基于快照行情的股票/基金 1分钟 K 线合成指南

1. 概述 由于不同交易所不同资产的交易规则是有差异的,导致不同交易所基于快照行情或逐笔成交合成不同资产1分钟 K 线的计算方法是不同的。 本教程旨在提高 DolphinDB 在具体业务场景下的落地效率,降低 DolphinDB 在实际业务使用中的开发难度。 本教程…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《含状态耦合约束的分布式船舶储能系统两层能量管理方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

计算机科学与导论 第十六章 安全

文章预览: 16.1引言16.1.1 安全目标16.1.2 攻击 16.2机密性16.2.1 对称密钥密码术16.2.2 非对称密钥密码术 16.1引言 为了安全,信息需要避开未授权的使用(机密性),保护信息不受到未授权的篡改(完整性),并且对于得到授权的实体来说是需要时可…

uniapp之消除图片的空白占用空间

我们在使用uniapp开发的过程中一定会遇到一个情况就是我们加载的图片总有一点空白出现在不该出现的地方代码如下 <view style"background:#ff0000;"><image style"width:100%;"src"https://t7.baidu.com/it/u1819248061,230866778&fm19…

selenium_定位输入框并输入值_CLASS_NAME

找到class_name # 导包 from selenium import webdriver from time import sleep# 获取浏览器对象 from selenium.webdriver.common.by import Bydriver webdriver.Edge() # 打开url url r"C:\Users\黄永生\Desktop\软件测试\tpshop\web自动化_day01_课件笔记资料代码\0…

【面试经典 150 | 链表】分隔链表

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;模拟 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…
最新文章