中间件

Posted kindvampire

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中间件相关的知识,希望对你有一定的参考价值。

中间件

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

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

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

我们一直都在使用中间件,只是没有注意到而已,打开Django项目的Settings.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,
]

中间件方法详解:

process_request(self,request)
参数:
?    request   请求的对象,和视图中的request是同一个
执行时间:视图函数之前
执行顺序:按照注册的顺序 顺序执行 
返回值:
?    None:正常流程                
    HttpReponse:当前中间件之后的中间件的process_request方法、路由匹配、视图也不执行,直接执行当前中间件的process_response方法

process_response(self, request, response) 参数: request:请求的对象,和视图中的request是同一个 ? response:返回的响应对象 执行时间:视图函数之后 执行顺序:按照注册的顺序 倒叙执行 返回值: HttpReponse: 必须返回响应对象 process_view(self, request, view_func, view_args, view_kwargs) 参数: ? request:请求的对象,和视图中的request是同一个 ? view_func:视图函数 ? view_args:视图函数的位置参数 ? view_kwargs:视图函数的关键字参数 执行时间:路由匹配之后,视图函数之前 执行顺序:按照注册的顺序 顺序执行 返回值: None:正常流程 ? HttpReponse: 当前中间件之后的process_view、视图不执行,执行最后一个中间的process_response
process_exception(self, request, exception) 参数: ? request:请求的对象,和视图中的request是同一个 ? exception:错误对象 执行时间(触发条件):视图层面有错误才执行 执行顺序:按照注册的顺序 倒叙执行 返回值 ? None:当前中间没有处理异常,交由下一个中间件处理异常,所有的中间件都没有处理,Django处理错误 ? HttpReponse: 当前中间处理好异常,之后执行最后一个中间件的process_response方法 pocess_template_response(self,request,response) 参数: ? request:请求的对象,和视图中的request是同一个 ? response:返回的响应对象 执行时间:视图必须返回一个template_response对象 执行顺序:按照注册的顺序 倒叙执行 返回值 HttpReponse: 必须返回响应对象

中间件的执行流程

技术图片

 

 请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法,将HttpResponse对象返回给浏览器。也就是说:如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第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两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

技术图片

 

 

技术图片

 

 Django的请求流程

技术图片

 

 附:中间件登录验证

技术图片

 

 中间件注册

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,
    crm.middlewares.Login_required
]

中间件内容

from django.utils.deprecation import MiddlewareMixin
from django.urls import reverse
from django.shortcuts import redirect, render, HttpResponse
from crm import models


class Login_required(MiddlewareMixin):
    def process_request(self, request):
        is_login = request.session.get(is_login)
        if request.path_info in [reverse(login), reverse(reg), request.path_info.startswith(/admin)]:
            return
        if not is_login:
            return redirect(login)
        else:
            request.user_obj = models.UserProfile.objects.filter(pk=request.session.get(pk)).first()

路由:

from django.conf.urls import url, include
from django.contrib import admin
from crm import views
urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^login/, views.Login.as_view(), name=login),
    url(r^crm/, include(crm.urls, namespace=crm)),
    url(r^reg/, views.Regisiter.as_view(), name=reg),

]

登录函数

class Login(View):
    def get(self, request):
        return render(request, login.html, locals())

    def post(self, request):
        username = request.POST.get(username)
        password = request.POST.get(password)
        obj = models.UserProfile.objects.filter(username=username, password=password, is_active=True)
        if obj:
            request.session.setdefault(is_login, 1)
            request.session[pk] = obj.first().pk
            return redirect(crm:customer)
        else:
            error = 用户名或密码错误!
            return render(request, login.html, locals())

 

以上是关于中间件的主要内容,如果未能解决你的问题,请参考以下文章

Sublime Text3自定义代码片段

无法更新 View Pager 中的中间片段。

Android - 从堆栈中间删除特定片段不起作用

从没有中间转换变量的片段中观察 ViewModel LiveData

如何将数据从顶点着色器传递到片段着色器,中间有着色器[重复]

如何定义对话框片段的重力?