Django中间件

Django中间件

只要是涉及到全局相关的功能都可以使用中间件方便的完成

  • 全局用户身份校验
  • 全局用户权限校验
  • 全局访问频率校验
"""
django中间件是django的门户
	1.请求来的时候需要经过中间件才能达到真正的django后端
	2.响应走的时候最后也需要经过中间件才能发送出去
"""

image-20221109184718273

1、默认中间件源码分析

class SecurityMiddleware(MiddlewareMixin):
        def process_request(self, request):
            path = request.path.lstrip("/")
            if (
                self.redirect
                and not request.is_secure()
                and not any(pattern.search(path) for pattern in self.redirect_exempt)
            ):
                host = self.redirect_host or request.get_host()
                return HttpResponsePermanentRedirect(
                    "https://%s%s" % (host, request.get_full_path())
                )

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


class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.user = SimpleLazyObject(lambda: get_user(request))


class CsrfViewMiddleware(MiddlewareMixin):
     def process_request(self, request):
        try:
            csrf_secret = self._get_secret(request)
        except InvalidTokenFormat:
            _add_new_csrf_cookie(request)
        else:
            if csrf_secret is not None:
                request.META["CSRF_COOKIE"] = csrf_secret

    def process_view(self, request, callback, callback_args, callback_kwargs):
        return self._accept(request)
   
    def process_response(self, request, response):
        return response
"""

django支持程序员自定义中间件,并且暴露给程序员五个可以自定义的方法
	1.必须了解
	process_request
	
	process_response
	2.了解即可
	process_view
	
	process_template_response
	
	process_exception
"""    

2、自定义中间件

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

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(掌握)

image-20221109191456363

启动项目,查看中间件是否生效

image-20221109191548177

添加一个路由,写一个视图函数,查看执行顺序

from django.contrib import admin
from django.urls import path
from App import  views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
]
# Create your views here.
def index(request):
    print('我是视图函数index')
    return HttpResponse('index')

启动项目,浏览器输入路由

image-20221109192047022

再写一个中间件,并颠倒注册顺序

image-20221109192636506

添加返回值

image-20221109194306420

总结:

  1. 请求来的时候是要经过每一个中间件里的process_request方法,结果的顺序按照配置文件中注册的中间件从上往下的顺序依次执行

  2. 如果中间件里面没有定义process_request方法,直接跳过,执行下一个

  3. 如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行,而是直接原路返回(校验失败,不允许访问)

    1. 所以process_request方法就是用来做全局相关的所有限制功能

process_response(掌握)

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse


class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第一个自定义中间件里面的process_request方法')

    def process_response(self, request, response):
        print('我是第一个自定义中间件里面的process_response方法')

        """

        :param request:
        :param response: django后端返回给浏览器的内容
        :return:
        """
        return response


class MyMiddleWare2(MiddlewareMixin):
    def process_request(self, request):
        print('我是第二个自定义中间件里面的process_request方法')

    def process_response(self, request, response):
        print('我是第二个自定义中间件里面的process_response方法')
        return response

浏览器输入路由,回车

image-20221109195429437

返回自己的HttpResponse对象

原本后端是要返回index的,走到中间件里面,先经过MyMiddleWare,返回index,但是经过MyMiddleWare2的时候来了一个偷天换日,把原本想要返回的响应换成自己的hello!,之后所有的中间件拿到的全是自己写的返回响应的内容

image-20221109195712980

总结:

  1. 响应走的时候需要经过每一个中间件里的process_response方法,该方法有两个额外的参数(request,response)

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

    1. 默认返回的就是形参response,
    2. 也可以自己返回自己的HttpResponse对象
  3. 顺序是按照配置文件中注册了的中间件从下往上依次经过,如果没有定义,直接执行上一个


如果在先注册了的中间件中的process_request方法就已经返回了HttpResponse对象,那么响应走的时候经过所有的中间件里面的process_response是否有其他情况?

image-20221109201241624

观察上图得出以下结论

​ 首先请求来的时候,会依次经过每一个注册了的中间件里的process_request方法,一旦process_request方法返回了一个HttpResponse对象,那么会直接不再往下走,而是直接经过同级别的process_response往外走。

image-20221109201546542


image-20221109201702210

process_view(了解)

def process_view(self, request, view_name, *args, **kwargs):
    print(view_name, args, kwargs)
    print('我是第一个自定义中间件里的process_view')

特点:

路由匹配成功之后,执行视图函数之前,会自动执行中间件里面的process_view方法,顺序按照配置文件中注册的中间件从上往下的顺序依次执行

image-20221109203106289

process_template_response(了解)

def process_response(self, request, response):
    print('我是第二个自定义中间件里面的process_response方法')
    return response
# views.py

def index(request):
    print('我是视图函数index')
    obj = HttpResponse('index')

    def render():
        print('内部的render')
        return HttpResponse('98K')

    obj.render = render
    return obj

返回的HttpResponse对象有render属性的时候,才会触发,顺序是

按照配置文件中注册的中间件从下往上依次经过

image-20221109204530848

process_execption(了解)

def process_exception(self, request, exception):
    print(exception)
    print('我是第二个自定义中间件里的process_exception')

当视图函数中出现异常的情况下,触发。

顺序是按照配置文件中注册的中间件从下往上依次经过

image-20221109205002531

全部代码:

# -*- coding: UTF-8 -*- 
# @Date :2022/11/9 19:03
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse


class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print('我是第一个自定义中间件里面的process_request方法')

    def process_response(self, request, response):
        print('我是第一个自定义中间件里面的process_response方法')

        """

        :param request:
        :param response: django后端返回给浏览器的内容
        :return:
        """
        return response

    def process_view(self, request, view_name, *args, **kwargs):
        print(view_name, args, kwargs)
        print('我是第一个自定义中间件里的process_view')

    def process_template_response(self, resquest, response):
        print('我是第一个自定义中间件里的process_template_response')
        return response

    def process_exception(self, request, exception):
        print(exception)
        print('我是第一个自定义中间件里的process_exception')


class MyMiddleWare2(MiddlewareMixin):
    def process_request(self, request):
        print('我是第二个自定义中间件里面的process_request方法')
        # return HttpResponse('JayChou')

    def process_response(self, request, response):
        print('我是第二个自定义中间件里面的process_response方法')
        return response
        # return HttpResponse('hello !')

    def process_view(self, request, view_name, *args, **kwargs):
        print(view_name, args, kwargs)
        print('我是第二个自定义中间件里的process_view')

    def process_template_response(self, resquest, response):
        print('我是第二个自定义中间件里的process_template_response')
        return response

    def process_exception(self, request, exception):
        print(exception)
        print('我是第二个自定义中间件里的process_exception')
posted @ 2022-12-12 16:55  ExpiredSaury  阅读(37)  评论(0编辑  收藏  举报