广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Django之中间件
  • 196
分享到

Django之中间件

中间件Django 2023-01-30 22:01:23 196人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

中间件介绍   中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变DjanGo的输入和输出。每个中间件组件都负责做一些特定的功能。   但是由于其影响的是全局,所以需要谨慎使

中间件介绍

 

中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变DjanGo的输入和输出。每个中间件组件都负责做一些特定的功能。

 

但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。

 

说的直白一点中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在处理请求的特定的时间去执行这些方法。

  在Django项目的Settings.py文件中,可以看到MIDDLEWARE配置:

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配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个个类,也就是一个个中间件.

我们之前已经接触过一个csrf相关的中间件了?我们一开始让大家把他注释掉,再提交post请求的时候,就不会被forbidden了,后来学会使用csrf_token之后就不再注释这个中间件了。

 

自定义中间件

  中间件可以定义五个方法,分别是:(主要的是process_request和process_response) 

  • process_request(self,request)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照Django定义的规则向后继续执行,如果是HttResponse对象,则直接将该对象返回给用户.

 

示例

from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

 

process_request方法

 

  参数: request  (和视图函数中的request是一样的)

  返回值: None 返回值是None,按正常流程走,交给下一个中间件;

       HttpResponse对象 若是此值,Django将不执行当前中间件后面的中间件的process_request方法和视图函数,执行当前中间件的process_response方法或之前中间件的process_response方法.

  执行时间:  该中间件方法是在视图函数执行前执行;

  执行顺序:  配置多个中间件时,按照注册顺序的先后顺序执行.

 

 当多个中间件时 ,Django如何执行process_request方法:

from django.utils.deprecation import MiddlewareMixin

# 定义俩个中间件的类
class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request")

 

  在Setting.py的MIDDLEWARE配置项中注册上述俩个定义中间件:

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',
    'middlewares.MD1',  # 注册自定义中间件MD1路径
    'middlewares.MD2'  # 注册自定义中间件MD2路径
]

 

 

  接着访问一个视图,终端打印内容如下:

MD2里面的 process_request
MD1里面的 process_request
app01 中的 index视图

  结果得知: 视图函数还是最后执行,MD2比MD1先执行自己的process_request方法.  不同中间件之间传递的request都是同一个对象

 

process_response方法

 

  参数: request  视图函数中用到的request 

      response  视图函数返回的HttpResponse对象.

  执行时间  在视图函数执行之后

  执行顺序  多个中间件的process_response方法是按照执行顺序的倒序执行

  返回值  必须是response(HttpResponse对象)

给上述M1和M2加上process_response方法:

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

  访问一个视图,看一下终端输出: 

MD2里面的 process_request
MD1里面的 process_request
app01 中的 index视图
MD1里面的 process_response
MD2里面的 process_response

  看结果可知:

多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。

 

process-view方法

 

process_view(self,request,view_func,view_args,view_kwargs)

  参数: request;

      view_func:  是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。);

      view_args:  是将传递给视图的位置参数;

      view_kwargs:   是将传递给视图的关键字参数。 view_args和view_kwargs都不包含第一个视图参数(request);

  返回值:   None Django将继续处理这个请求,执行任何其他中间件的process_view 方法,然后在执行相应的视图.

      HttpResponse对象. 如果返回一个HttPResponse对象,Django不会调用适当的视图函数. 他将执行中间件的process_response方法并将应用到该HttpResponse并返回结果.

  执行时间: 在视图函数之前,process_request之后

  执行顺序:   按照注册顺序先后执行

 

给MD1和MD2添加process_view方法:

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

访问index视图函数,看一下输出结果:

MD2里面的 process_request
MD1里面的 process_request
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001DE68317488> index
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001DE68317488> index
app01 中的 index视图
MD1里面的 process_response
MD2里面的 process_response

process_view方法是在process_request之后,视图函数之前执行的,执行顺序按照MIDDLEWARE中注册顺序从前到后顺序执行的.

 

process_exception(self, request, exception)方法

 

 参数:

  HttpRequest对象

  exception  是视图函数异常产生的Exception对象.

  执行时间:  在视图函数之后,process_response方法之前       这个方法只有在视图函数中出现异常了才执行,

  返回值: None 交给下一个中间件的process_exception方法来处理异常.

       HttpResponse对象 Django将执行所有中间件的process_response方法; 该中间件方法注册之前的中间件的process_exception方法不走了.

  执行顺序:  他的执行顺序也是按照中间件注册顺序的倒序执行.

 

给MD1和MD2添加上这个方法:

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2里面的 process_request")

    def process_response(self, request, response):
        print("MD2里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD2 中的process_exception")

如果视图函数中无异常,process_exception方法不执行.

想办法,在视图中抛出异常:

def index(request):
    print("app01 中的 index视图")
    raise ValueError("呵呵")
    return HttpResponse("O98K")

 

在MD1的process_exception中返回一个响应对象:

class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")
        return HttpResponse(str(exception))  # 返回一个响应对象

输出结果:

MD2里面的 process_request
MD1里面的 process_request
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x0000022C09727488> index
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x0000022C09727488> index
app01 中的 index视图
呵呵
MD1 中的process_exception
MD1里面的 process_response
MD2里面的 process_response

注意: 这里并没有执行MD2的process_exception方法,因为MD1中process_exception方法直接返回了一个响应对象.

 

process_template-response方法

 

process-template_response(self, request, response)

  参数 HttpRequest对象,

     response  TemplateResponse对象(由视图函数或者中间件产生).

  执行时间  是在视图函数执行完成后立即执行,但是他有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法).

  执行顺序  按照注册顺序倒序执行

  返回值  response对象

class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1里面的 process_request")

    def process_response(self, request, response):
        print("MD1里面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")
        return HttpResponse(str(exception))

    def process_template_response(self, request, response):
        print("MD1 中的process_template_response")
        return response
class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") def process_response(self, request, response): print("MD2里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("MD2 中的process_exception") def process_template_response(self, request, response): print("MD2 中的process_template_response") return response

views.py中:

def index(request):
    print("app01 中的 index视图")

    def render():
        print("in index/render")
        return HttpResponse("O98K")
    rep = HttpResponse("OK")
    rep.render = render
    return rep

访问index视图,终端输出结果:

MD2里面的 process_request
MD1里面的 process_request
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001C111B97488> index
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001C111B97488> index
app01 中的 index视图
MD1 中的process_template_response
MD2 中的process_template_response
in index/render
MD1里面的 process_response
MD2里面的 process_response

从结果得知:

视图函数执行完成之后,立即执行了中间件的process_response方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法.

 

中间件的执行流程

请求到达中间件之后,先按照正序执行每个注册中间件的process_request方法,process_request方法返回的值是None,就依次执行,如果返回的是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_request方法,将HttpResponse对象返回给浏览器.也就是说MIDDLEMARE中注册了六个中间件,执行过程中,第三个中间件返回Response对象,那么第4,5,6 中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process-response方法.

process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。假如中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。

process_template_response和process_exception俩个方法的触发是有条件的,执行顺序也是倒序.总结所有的执行流程如下:

中间件登录验证

 

中间件版的登录验证需要session,所以数据库中药有django_session表

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/$', views.login, name='login'),
    url(r'^index/$', views.index, name='index'),
    url(r'^home/$', views.home, name='home'),
]

views.py

from django.shortcuts import render, HttpResponse, redirect


def index(request):
    return HttpResponse('this is index')


def home(request):
    return HttpResponse('this is home')


def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "alex" and pwd == "alex3714":
            # 设置session
            request.session["user"] = user
            # 获取跳到登陆页面之前的URL
            next_url = request.GET.get("next")
            # 如果有,就跳转回登陆之前的URL
            if next_url:
                return redirect(next_url)
            # 否则默认跳转到index页面
            else:
                return redirect("/index/")
    return render(request, "login.html")

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>登录页面</title>
</head>
<body>
<fORM action="{% url 'login' %}" method="post">
    {% csrf_token %}
    <p>
        <label for="user">用户名:</label>
        <input type="text" name="user" id="user">
    </p>
    <p>
        <label for="pwd">密 码:</label>
        <input type="text" name="pwd" id="pwd">
    </p>
    <input type="submit" value="登录">
</form>
</body>
</html>

middlewares.py

from django.utils.deprecation import MiddlewareMixin


class AuthMD(MiddlewareMixin):
    white_list = ['/login/', ]  # 白名单
    black_list = ['/black/', ]  # 黑名单

    def process_request(self, request):
        from django.shortcuts import redirect, HttpResponse

        next_url = request.path_info
        print(request.path_info, request.get_full_path())
        # 黑名单的网址限制访问
        if next_url in self.black_list:
            return HttpResponse('This is an illegal URL')
        # 白名单的网址或者登陆用户不做限制
        elif next_url in self.white_list or request.session.get("user"):
            return
        else:
            return redirect("/login/?next={}".format(next_url))

在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',
    'middlewares.AuthMD'
]

AuthMD中间件注册后,所有的请求都要走AuthMD的process_request方法。

如果URL在黑名单中,则返回This is an illegal URL的字符串;

访问的URL在白名单内或者session中有user用户名,则不做阻拦走正常流程;

正常的URL但是需要登录后访问,让浏览器跳转到登录页面。

注:AuthMD中间件中需要session,所以AuthMD注册的位置要在session中间的下方.

 

Django请求流程图

正常过程 : 浏览器发请求---wsgi封装成HttpRequest对象---中间件的process_request方法---路由匹配---中间件中的process_view方法---视图函数---模板(Template) | Model | 有HttpResponse对象,就执行process_response方法.

特殊情况: 示图某方法有返回response对象,就会执行process_response方法;

     出现错误就会执行exception方法处理,若都出现错误,Django会处理错误,处理完成后还要执行process_response方法.

 

--结束END--

本文标题: Django之中间件

本文链接: https://www.lsjlt.com/news/179993.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Django之中间件
    中间件介绍   中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。   但是由于其影响的是全局,所以需要谨慎使...
    99+
    2023-01-30
    中间件 Django
  • day 63 Django基础九之中间件
        本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏      我们在前面的课程中已经学会了...
    99+
    2023-01-31
    中间件 基础 day
  • Django 中间件
    目录 一.中间件 二.中间件用途 三.中间件方法 四.自定义中间件 process_view proc...
    99+
    2023-01-30
    中间件 Django
  • django中间件-12
    目录 自定义中间件 函数定义 类定义 中间件的执行顺序 在django中,中间件其实...
    99+
    2023-01-30
    中间件 django
  • Django 中间件 请求前
    中间件: class TestMiddleware(object): """中间件类""" def __init__(self): """服务器重启之后,接收第一个请求时调用""" pas...
    99+
    2023-01-30
    中间件 Django
  • Django中间件的使用
    中间件(middleware) 中间件应用于request与服务端之间和服务端与response之间,客户端发起请求到服务端接收可以通过中间件,服务端返回响应与客户端接收响应可以通过中间件,也就是说中间件可以处理request和resp...
    99+
    2023-01-30
    中间件 Django
  • Django的中间件是什么
    本篇内容主要讲解“Django的中间件是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Django的中间件是什么”吧!什么是中间件(middleware) django 中的中间件(midd...
    99+
    2023-06-04
  • Django——中间件设置缓存
    如图所示查看网站缓存时间 在app中创建middleware.py文件,导入MiddlewareMixin,创建类并继承MiddlewareMixin 在settings中的MIDDLEWARE=[ ] 注册中间件类;添加一个CAC...
    99+
    2023-01-30
    缓存 中间件 Django
  • Django之auth组件
    一、Auth模块是什么   django内置的用户认证系统 ,可以快速 的实现,登录,注销,修改密码... 二、Auth用法:   1、先创建超级用户 :      python3 manage.py createsuperuser; ...
    99+
    2023-01-30
    组件 Django auth
  • Django之forms组件
      一、校验数据功能   我们在写注册页面时,之前只是提交了数据,然后就保存了数据,后端根本就没有对数据进行校验,比如价格写的不是纯数字也让保存,这肯定是不行的,在前端是可以校验的,但我们不能只依靠前端验证,万一前端不校验,那整个过程就没...
    99+
    2023-01-30
    组件 Django forms
  • Django之Form组件
    一 Form介绍      我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。   与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度...
    99+
    2023-01-30
    组件 Django Form
  • 如何在Go和Django之间构建接口文件?
    在当今的软件开发中,构建API(应用程序接口)是非常重要的一项工作。这些接口允许不同的应用程序之间进行通信,并共享数据和功能。在构建接口时,选择合适的技术和框架是至关重要的。Go和Django是两个非常流行的框架,本文将介绍如何在这两个框架...
    99+
    2023-08-25
    django 接口 文件
  • Django之频率组件
    一、频率简介 为了控制用户对某个url的请求 的频率,比如 ,一分钟以内,只能访问三次 二、自定义频率类,自定义频率规则 自定义的逻辑 (1)取出访问者的ip (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一...
    99+
    2023-01-30
    组件 频率 Django
  • 探索Go和Django之间的接口文件交互方式?
    Go语言和Django框架都是目前非常流行的开发工具,它们都有各自的优点和适用场景。在实际开发中,我们可能会遇到Go和Django之间需要进行接口文件交互的情况,那么有哪些方式可以实现呢? 一、使用HTTP协议进行交互 HTTP协议是常用的...
    99+
    2023-08-25
    django 接口 文件
  • Django之Ajax文件上传
     请求头ContentType     ContentType指的是请求体的编码类型,常见的类型共有3种:     1 application/x-www-form-urlencoded(看下图)       这应该是最常见的 POST ...
    99+
    2023-01-30
    文件上传 Django Ajax
  • ASP.NETCore基础之中间件
    什么是ASP.NET Core Middleware? ASP.NET Core中间件组件是被组装到应用程序管道中以处理HTTP请求和响应的软件组件(从技术上来说,组件只是C#类)。...
    99+
    2022-11-13
    ASP.NET Core 中间件
  • Django之用户认证组件
      用户认证组件用的是Django自带一个表:auth_user   一、auth模块   1,authenticate()判断用户是否存在方法 user=authenticate(username='xxx',password='xx...
    99+
    2023-01-30
    组件 用户 Django
  • django-10-中间件和上下文管理器
    <<<中间件的引入>>> 用户<->中间件<->url->视图  在app目录里面 middleware.py  (1)中间件就是一个可调用的对象,接受一个request并...
    99+
    2023-01-31
    上下文 管理器 中间件
  • Django学习之八:forms组件【对
    目录 Django forms组件 bound and unbound form instance forms渲染有关 隐藏一个字段...
    99+
    2023-01-30
    组件 Django forms
  • Django中间件整合Vue拦截器的使用
    目录axios拦截器是什么?拦截器的使用请求拦截器响应拦截器Django中间件token验证中间件相关自定义中间件中间件的执行流程用中间件进行登录认证总结axios拦截器是什么? ...
    99+
    2022-11-12
    Django Vue拦截器 Django 拦截器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作