由浅入深:Django中间件原理及编程步骤

这篇具有很好参考价值的文章主要介绍了由浅入深:Django中间件原理及编程步骤。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文主要内容🍑

  • 什么是 Django 中的中间件?
  • 中间件如何工作?
  • 中间件有哪些类型?
  • 如何在 Django 中编写自定义中间件?

1、Django中间件的基础知识

1.1 什么是 Django 的中间件?**

通俗地说👨 ,中间件是充当程序或系统两个部分之间的桥梁,使它们之间的通信成为可能。在技术术语👨 💻中,中间件是Django的请求/响应处理的钩子框架。它是一个轻量级的低级“插件”系统,用于全局更改 Django 的输入或输出。每个中间件组件负责执行某些特定功能。

1.2 中间件如何工作?🤔

中间件middleware 就是view 执行前、执行后的回调函数, 流程可以简单地描述如下

当用户向你的 Django 应用程序发出Request请求时,它首先通过中间件管道,然后再到达你的视图函数。请求按照在应用程序的中间件设置中定义中间件类的顺序进行处理。

管道中的每个中间件类负责处理特定任务或向请求处理添加功能。中间件类可以:

  • 处理需求,如检查请求头参数,URL地址合法性等,并传递给视图函数
  • 处理请求并立即返回响应,绕过其余的中间件类和视图函数。
  • 处理请求并将其传递给管道中的下一个中间件类, 则应调用下一个中间件类的 get_response 方法,将请求对象作为参数传递。

视图函数发出Response后,会将Response发送给中间件层, 经过中间件处理完成后,再发送给WSGI, 返还给用户。

Response响应处理
一旦请求到达视图函数,它就会被处理,并生成响应。然后,响应以相反的顺序流回中间件管道。每个中间件类都可以修改响应、添加标头或执行其他任务,然后再将其传递给管道中的上一个中间件类。

在此阶段,中间件类应处理响应对象并返回它,从而允许管道中的前一个中间件类进一步处理响应。

1.3 中间件的应用场景:

  • 反爬虫场景,分析request的源IP访问次数等
  • 禁止特定IP地址的用户或未登录的用户访问我们的View视图函数
  • 在View视图函数执行前传递额外的变量或参数
  • 在View视图函数执行后对response数据进行修改后返回给用户
  • 在View视图函数执行前或执行后把特定信息打印到log日志
  1. 中间件有哪些类型?

Django 中有两种类型的中间件:

  • 内置中间件

  • 自定义中间件

内置中间件,当你创建项目时,Django 默认提供内置中间件。您可以在项目的 settings.py 文件中检查默认中间件。
自定义中间件 — 您可以编写自己的中间件,该中间件可以在整个项目中使用。

3. 如何在 Django 中编写自定义中间件?✍

3.1 自定义中间件步骤

自定义中间件你首先要在app所属目录下新建一个文件middleware.py(或任何您喜欢的文件名), 添加好编写的中间件代码,然后在项目settings.py中把它添加到MIDDLEWARE列表进行注册,添加时一定要注意顺序。

您可以将中间件编写为函数或实例可调用的类。

  • 基于函数的中间件
  • 基于类的中间件

3.2 基于函数的中间件

在middleware.py中输入如下代码

import time

def timeit_middleware(get_response):
    
    def middleware(request):
        start = time.time()
        response = get_response(request)
        end = time.time()
        print("请求花费时间: {}秒".format(end - start))
        return response

    return middleware

在项目 settings.py 中注册中间件

MIDDLEWARE = [
    ....
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'blog.middleware.timeit_middleware', # 新增
]

response = get_response(request) 是分界面,在此之前的代码执行完成后, 按顺序执行下一个中间件,如无,则跳到view。

3.3 使用类来编程自定义中间件

我们现在以类来编写一个名为LoginRequiredMiddleware的中间件,实现全站要求登录,但是登录页面和开放白名单上的urls除外。代码如下所示:

from django.shortcuts import redirect
from django.conf import settings

class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.login_url = settings.LOGIN_URL
        # 开放白名单,比如['/login/', '/admin/']
        self.open_urls = [self.login_url] + getattr(settings, 'OPEN_URLS', [])

    def __call__(self, request):        
        if not request.user.is_authenticated and request.path_info not in self.open_urls:
            return redirect(self.login_url + '?next=' + request.get_full_path())
        
        response = self.get_response(request) 
        return response

注册中间件

MIDDLEWARE = [

    'blog.middleware.simple_middleware',
    'blog.middleware.LoginRequiredMiddleware',   # new middleware class 
]

LOGIN_URL = "/admin/login/"
OPEN_URLS = ["/admin/"]

3.4 其它中间件钩子函数

Django还提供了其它的中间件钩子函数,分别在执行视图函数,处理异常和进行模板渲染时调用。

  • process_request:当 Django 在每个中间件中通过process_request方法时,将创建请求对象。之后,它会在设置文件中的键的帮助下解析在创建请求对象后不久要调用ROOT_URLCONF视图。
  • process_view(request, view_func, view_args, view_kwargs):request 是 HttpRequest 对象,view_func 是正在调用的函数。它将在调用视图之前被调用。
  • process_response:响应将是 Django 在每个中间件中执行 process_response 方法后将处理的最终输出,该中间件将是 HttpResponse 对象。
  • process_template_response(request, response):request 是一个 HttpRequest 对象。响应是由 Django 视图或中间件返回的 TemplateResponse 对象(或等效对象)。
  • process_exception(request, exception):request 是一个 HttpRequest 对象。异常是由视图函数引发的异常对象。当视图引发异常时,将调用此方法。

函数中间件如何使用钩子函数:

from django.http import HttpResponse

def timeit_middleware(get_response):
    
    def middleware(request):
        response = get_response(request)
        return response
    
    def process_view(request, view_func, view_args, view_kwargs)
        return None or HttpResponse(xx)
 
    def process_exception(self, request, exception):
        return None or HttpResponse(xx)
    
    def process_template_response(self, request, response)
        return ...
    
    middleware.process_view = process_view
    middleware.process_exception = process_exception
    middleware.process_template_response = process_template_response
 
    return middleware

以类的方 法实现

class MyClassMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
 
    def __call__(self, request):
        return self.get_response(request)
    
    def process_view(request, view_func, view_args, view_kwargs)
        return None or HttpResponse(xx)
 
    def process_exception(self, request, exception):
        return None or HttpResponse(xx)
        # 例子: 打印出异常
        return HttpResponse(<h1>str(exception)</h1)
    
    # 该方法仅对TemplateResponse输入有用,对render方法失效
    def process_template_response(self, request, response)
        response.context_data['title'] = 'New title'
        return response

4. 常见的自定义中间件

除了前面章节示例中的检查用户是否登录的中间件外,下面列出几个常见的自定中间件,实际项目中可以在此基础上进行扩展。

4.1 记录传入Request 日志的中间件

此中间件记录每个传入请求的详细信息,例如请求方法、路径和客户端 IP 地址。这对于调试和监视目的非常有用。

import logging

logger = logging.getLogger(__name__)

class RequestLoggingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        logger.info(f"Request: {request.method} {request.path} from {request.META['REMOTE_ADDR']}")
        response = self.get_response(request)
        return response

4.2 维护模式中间件

此中间件检查应用程序是否处于维护模式,并为所有请求(来自特定 IP 地址的请求除外)返回自定义维护页面。

from django.http import HttpResponse
from django.template import loader

class MaintenanceModeMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        maintenance_mode = False # Set this to True when maintenance mode is enabled
        allowed_ips = ['127.0.0.1'] # List of allowed IP addresses

        if maintenance_mode and request.META['REMOTE_ADDR'] not in allowed_ips:
            template = loader.get_template('maintenance.html')
            return HttpResponse(template.render(), content_type='text/html', status=503)

        response = self.get_response(request)
        return response

4.3. API Key 检查中间件

此中间件检查请求在标头中是否包含有效的 API 密钥,如果密钥丢失或无效,则返回 HTTP 401 未授权响应。

from django.http import JsonResponse

class ApiKeyAuthenticationMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        api_key = request.META.get('HTTP_X_API_KEY')
        valid_api_keys = ['your_valid_api_key'] # Replace this with your list of valid API keys

        if not api_key or api_key not in valid_api_keys:
            return JsonResponse({'error': 'Unauthorized'}, status=401)

        response = self.get_response(request)
        return response

4.4.异常处理中间件

此中间件捕获在请求/响应周期中引发的异常并记录错误,以 JSON 格式返回自定义错误响应。

import logging

logger = logging.getLogger(__name__)

class ExceptionHandlingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        try:
            response = self.get_response(request)
        except Exception as e:
            logger.exception(e)
            return JsonResponse({'error': 'An unexpected error occurred'}, status=500)

        return response

5. 使用中间件时要记住的事项

👉 中间件的顺序很重要。
👉 中间件只需要从类对象扩展。
👉 自定义中间件可以使用钩子函数来满足不同阶段的处理要求。文章来源地址https://www.toymoban.com/news/detail-569485.html

到了这里,关于由浅入深:Django中间件原理及编程步骤的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React - redux 使用(由浅入深)

    中文文档: http://www.redux.org.cn/ 英文文档: https://redux.js.org/ Github: https://github.com/reactjs/redux 可直接参照 目录十 进行使用 react-redux redux 是一个专门用于做状态管理的JS库(不是react插件库)。 它可以用在 react, angular, vue 等项目中, 但基本与 react 配合使用。 作用: 集中式管理 re

    2024年02月07日
    浏览(52)
  • 由浅入深理解C#中的事件

    本文较长,给大家提供了目录,可以直接看自己感兴趣的部分。 前面介绍了C#中的委托,事件的很多部分都与委托类似。实际上,事件就像是专门用于某种特殊用途的简单委托,事件包含了一个私有的委托,如下图所示: 有关事件的私有委托需要了解的重要事项如下: 1、事

    2024年02月03日
    浏览(43)
  • 【由浅入深学习MySQL】之索引进阶

    本系列为:MySQL数据库详解,为千锋资深教学老师独家创作 致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【关注】持续追更~ 文末有本文重点总结,技术类问题,也欢迎大家和我们沟通交流! 从今天开始本系列

    2024年02月05日
    浏览(45)
  • 手拉手Vue组件由浅入深

    组件 (Component) 是 Vue.js 最强大的功能之一,它是html、css、js等的一个聚合体,封装性和隔离性非常强。 组件化开发:     1、将一个具备完整功能的项目的一部分分割多处使用     2、加快项目的进度     3、可以进行项目的复用 组件注册分为:全局注册和局部注册 目录

    2024年01月18日
    浏览(46)
  • 由浅入深介绍 Python Websocket 编程

    1.1 websocket 协议简介 Websocket协议是对http的改进,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持,直到client或server 中断连接,弥补了http无法保持长连接的不足,方便了客户端应用与服务器之间实时通信。 适用场景 html页面实时更新, 客户端的html页面

    2024年02月03日
    浏览(42)
  • Springboot3+EasyExcel由浅入深

    环境介绍 技术栈 springboot3+easyexcel 软件 版本 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3 EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。 他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。 官网https://easyexcel.opensource.ali

    2024年01月16日
    浏览(47)
  • 【由浅入深学MySQL】- MySQL连接查询

    本系列为:MySQL数据库详解,为千锋教育资深Java教学老师独家创作 致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【点个关注】持续追更~ 文末有重点总结和福利内容! 技术类问题,也欢迎大家和我们沟通交流!

    2024年02月05日
    浏览(63)
  • 什么是感知机——图文并茂,由浅入深

    生活中常常伴随着各种各样的逻辑判断,比如看到远方天空中飘来乌云,打开手机看到天气预报说1小时后40%的概率下雨,此时时候我们常常会做出等会下雨,出门带伞的判断。 上述思考过程可以抽象为一个”与“的”神经逻辑“。当”看到乌云“和”天气预报40%下雨“同时

    2023年04月20日
    浏览(41)
  • 由浅入深剖析 Apollo(阿波罗)架构

    目录 一、介绍 二、架构和模块 三、架构剖析 1.最简架构  2. 高可用保障  3.多接口扩展 四、总结 Apollo(阿波罗)是携程框架部研发并开源的一款生产级的配置中心产品,它能够集中管理应用在不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的

    2024年02月13日
    浏览(41)
  • 由浅入深了解机器学习和GPT原理

    我不是一个机器学习专家,本来是一名软件工程师,与人工智能的互动很少。我一直渴望深入了解机器学习,但一直没有找到适合自己的入门方式。这就是为什么,当谷歌在2015年11月开源TensorFlow时,我非常兴奋,知道是时候开始学习之旅了。不想过于夸张,但对我来说,这就

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包