django---中间件

django中间件

介绍

官方介绍:

中间件是一个钩子框架,它们可以介入Django 的请求和响应处理过程。 它是一个轻量级、底层的“插件”系统,用于在全局修改Django 的输入或输出。

介绍1:

首先django自带七个中间件,

每个中间件都有各自对应的功能

并且django还支持程序员自定义中间件

在用django开发项目的时候 只要设计到全局相关的功能都可以使用中间件方便的完成

  • 全局用户身份校验
  • 全局用户权限校验
  • 全局访问频率校验

介绍2:

HTTP Web服务器工作原理一般都是接收用户发来的请求(request), 然后给出响应(response)。

Django也不例外,其一般工作方式是接收request对象和其它参数,交由视图(view)处理,然后给出它的响应(respone)数据: 渲染过的html文件或json格式的数据。

然而在实际工作中Django并不是接收到request对象后,马上交给视图函数或类(view)处理,也不是在view执行后立马给用户返回reponse。

事实上Django最初接收的是HttpRequest对象,而不是request对象,正是中间件的作用把HttpRequest对象和user对象打包成了一个全局变量request对象,这样你才可以View中使用request作为变量或者在模板中随意调用request.user。

中间件(Middleware)在整个Django的request/response处理机制中的角色如下所示:

HttpRequest -> Middleware -> View -> Middleware -> HttpResponse

正是由于一个请求HttpRequest在传递给视图View处理前要经过中间件处理,经过View处理后的响应也要经过中间件处理才能返回给用户,我们可以编写自己的中间件实现权限校验,限制用户请求、打印日志、改变输出内容等多种应用场景,比如:

  • 禁止特定IP地址的用户或未登录的用户访问我们的View视图函数

  • 对同一IP地址单位时间内发送的请求数量做出限制

  • 在View视图函数执行前记录用户的IP地址

  • 在View视图函数执行前传递额外的变量或参数

  • 在View视图函数执行前或执行后把特定信息打印到log日志

  • 在View视图函数执行后对reponse数据进行修改后返回给用户

图解

django---中间件_第1张图片

2.django的七个内置中间价

介绍

MIDDLEWARE = [

     # 为请求/响应循环提供了几种安全改进
    'django.middleware.security.SecurityMiddleware',

     # 开启会话支持
    'django.contrib.sessions.middleware.SessionMiddleware',

     # 基于APPEND_SLASH和PREPEND_WWW的设置来重写URL

     # 如果APPEND_SLASH设为True,并且初始URL 没有以斜线结尾以及在URLconf 中没找到对应定义,这时形成一个斜线结尾的新URL
    'django.middleware.common.CommonMiddleware',

     # 添加跨站点请求伪造的保护,通过向POST表单添加一个隐藏的表单字段,并检查请求中是否有正确的值
    'django.middleware.csrf.CsrfViewMiddleware',

     #  向每个接收到的user对象添加HttpRequest属性,表示当前登录的用户
    'django.contrib.auth.middleware.AuthenticationMiddleware',

     # 开启基于Cookie和会话的消息支持
    'django.contrib.messages.middleware.MessageMiddleware',

     # 对点击劫持的保护
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

其他自带的中间件

1. 如果你要实现全站缓存, 还需要使用UpdateCacheMiddleware和FetchFromCacheMiddleware,但一定要注意它们的顺序,Update在前和Fetch在后。

MIDDLEWARE = [

'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware',

]

2.压缩网站内容的:GZipMiddleware,

根据用户请求语言返回不同内容:LocaleMiddleware

给GET请求附加条件:ConditionalGetMiddleware

注意Django的中间件执行顺序

1. MIDDLEWARE中的顺序很重要,因为中间件可以依赖于其他中间件
2. 当你在settings.py注册中间件时一定要要考虑中间件的执行顺序,在请求阶段,在调用视图之前,Django以MIDDLEWARE(自上而下)定义的顺序应用中间件

3. 在处理响应期间,中间件的执行顺序是从下往上的

4. 如果你自定义的中间件有依赖于request.user(比如判断用户是否登录),那么你自定义的中间件一定要放在AuthenticationMiddleware的后面。

3. 如何自定义中间件

介绍

1. 中间件类必须实现下列五个方法中的一个或多个

process_request(self,request):
作用:执行主路由之前被掉用,请求来的时候,需要经过每一个中间件里面的process_request方法 结果的顺序是按照,配置文件中注册的,中间件从上往下的顺序依次执行,如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件

返回None:请求通过,交给下一个中间价处理

返回HttpResponse对象:请求不通过,由当前中间价的,process_response直接往上一层层的返回
用途:过滤请求


process_view(self,request,callback,callback_args,callback_kwargs):
作用:

callback:为视图函数;

callback_args:视图函数的位置参数,

callback_kwargs:视图函数的关键字参数;调用视图之前被调用,在每个请求上调用

返回None:请求通过,交给下一个中间价处理

返回HttpResponse对象:请求不通过,由当前中间价的process_response直接往上一层层的返回

用途:用于代码层面的替换和过滤,这个方法可以拿到视图函数的参数


process_response(self,request,response):
作用:

response:是视图函数的响应对象;在响应返回浏览器之前被调用(完成视图的执行但还未把它返回给浏览器),在每个请求上走的时候,需要经过每一个中间件里面的process_response方法,顺序是按照配置文件中注册了的中间件从下往上依次经过,如果没有定义的话 直接跳过执行下一个

参数:该方法有两个额外的参数request,response

返回:该方法必须返回一个HttpResponse对象

1.默认返回的就是形参response

2.也可以自己返回自己的

注意:如果返回HttpResponse,会替换response,与process_request不同的是,会继续往上走,其上面的中间件拿到的response,都是被替换的HttpResponse


process_exception(self,request,exception):
作用:在执行视图时,发生的异常时被调用,返回一个HttpResponse对象
用途:用于一般用于捕获发生的异常,并将其邮件发送给开发人员


process_template_response(self,request,response):
作用:在视图函数执行完毕,且视图函数返回的对象中,包含render方法时被调用;

该方法需要返回实现了render方法的响应对象

__init__(get_response)

  • 必须配置get_response

flask框架也会有一个中间件 但是他的规律 只要返回数据了就必须经过所有中间件,里面的类似于process_response方法


注意:

中间件中的大多数方法在返回None时表示忽略当前操作进入下一项事件,当返回HttpResponse对象时,表示此请求结束,直接返回给客户端

HttpResponse

HttpResponse_骑台风走的博客-CSDN博客username = request.session.get('name', '游客')session:所有的数据存储在服务端,在客户端用cookie存储session_id。request.session.set_expiry(10) 设置为10秒后过期。# request.session.clear() # 方法2。request.session.flush() # 方法3。logout(request) # 方法1,推荐。http协议是无状态的,每次请求都是一次新的请求,它不记得之前的请求。https://blog.csdn.net/qq_52385631/article/details/126942861?spm=1001.2014.3001.5501

使用(django3.x以下)

介绍

  • 1.在项目名或者应用名下创建一个任意名称的文件夹
  • 2.在该文件夹内创建一个任意名称的py文件
  • 3.在该py文件内需要书写类(这个类必须继承MiddlewareMixin),然后在这个类里面就可以自定义五个方法了,(这五个方法并不是全部都需要书写,用几个写几个)
  • 4.需要将类的路径以字符串的形式注册到配置文件中才能生效

Middleware.py

from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
from django.shortcuts import HttpResponse, redirect


class MyMiddleware(MiddlewareMixin):
    def process_request(self, request):
        next_url = request.path_info
        if not request.path_info.startswith("/login/"):
            # 做登录验证
            login_flag = request.session.get("login", "")
            if not login_flag:
                return redirect("/login/?next={}".format(next_url))

    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    def process_exception(self, request, exception):
        if isinstance(exception, ValueError):
            return HttpResponse("404")

    def process_response(self, request, response):
        return response

settings.py

MIDDLEWARE = [
    ...
    'mymiddlewares.middlewares.MyMiddleware',

]

使用(django3.x以上)

Middleware.py

class MyFirstMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.一次性设置和初始化

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.
        print("接收到request请求,视图函数马上执行")
        if not request.user.is_authenticated:
            print("该请求用户尚未登录")

        response = self.get_response(request)
        # Code to be executed for each request/response after
        # the view is called. 视图函数执行后的代码
        print("视图函数执行结束,准备提供响应")

        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    def process_exception(self, request, exception):
        pass

    def process_template_response(self, request, response):
        pass
   

settings.py

因为我们自定义的中间件依赖于request对象,我们一定要放在AuthenticationMiddleware的后面


MIDDLEWARE = [
    ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'users.middleware.MyFirstMiddleware',
]

案例三

Middleware.py

MyDjango/myMiddleware.py:
from django.utils.deprecation import MiddlewareMixin


class MyMiddleware(MiddlewareMixin):
    def __init__(self, get_response=None):
        """运行Django将自动执行"""
        super().__init__(get_response)
        self.get_response = get_response
        print('This is __init__')

    def process_request(self, request):
        """生成请求对象后,路由匹配之前"""
        print('This is process_request')

    def process_view(self, request, func, args, kwargs):
        """路由匹配后,视图函数调用之前"""
        print('This is process_view')

    def process_exception(self, request, exception):
        """视图函数发生异常时"""
        print('This is process_exception')

    def process_response(self, request, response):
        """视图函数执行后,响应内容返回浏览器之前"""
        print('This is process_response')
        return response

settings.py

MIDDLEWARE = [
    ...
    'MyDjango.myMiddleware.MyMiddleware'
]

参考文章

(13条消息) Django学习(三):中间件_Lee-hua的博客-CSDN博客_django中间件

django HttpResponse对象 - 超级学渣渣 - 博客园 (cnblogs.com)

(13条消息) Django:中间件_dongys_z的博客-CSDN博客

(13条消息) Django—中间件详解_最萌毕加索的博客-CSDN博客_django中间件

(13条消息) django:中间件_dangfulin的博客-CSDN博客_django的中间件

Django基础(33): 中间件(middleware)的工作原理和应用场景举例 (qq.com)

你可能感兴趣的:(django,中间件,python)