什么是django中间件?(七个中间件-自定义中间件)

Posted [OJBK]

tags:

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

一:django中间件

1.什么是django中间件
Django中间件是Django的门户
1.请求来的时候需要先经过中间件才能到达真正的Django后端
2.响应走的时候最后也需要经过中间件才能发送出去
2.django请求生命周期流程图
  • Django的七个中间件

二: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\',
]
1.研究django中间件代码规律
1.以上django自带中间件看着是字符串,其实,它是一个模块,类。
2.其实django自带中间件是一条导入语句,只不过变成字符串的形式
# \'django.contrib.sessions.middleware.SessionMiddleware\'
class SessionMiddleware(MiddlewareMixin):
    def process_request(self, request):
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        request.session = self.SessionStore(session_key)
    def process_response(self, request, response):
        return response
  

# \'django.middleware.csrf.CsrfViewMiddleware\'
class CsrfViewMiddleware(MiddlewareMixin):
  	def process_request(self, request):
        csrf_token = self._get_token(request)
        if csrf_token is not None:
            # Use same token next time.
            request.META[\'CSRF_COOKIE\'] = csrf_token
    def process_view(self, request, callback, callback_args, callback_kwargs):
        return self._accept(request)

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

# \'django.contrib.auth.middleware.AuthenticationMiddleware\'
class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.user = SimpleLazyObject(lambda: get_user(request))

2.django支持程序员自定义中间件并且暴露给程序员五个可以自定义的方法
2.1必须掌握
process_request

process_response
2.2了解即可
process_view

process_template_response

process_exception

三:如何自定义中间件

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

2.以字符串的形式注册到配置文件才能生效
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\',
    \'你自己写的中间件的路径1\',
    \'你自己写的中间件的路径2\',
    \'你自己写的中间件的路径3\',
]

四:必须掌握(process_request与process_response )

1.process_request 请求来的时候效验
process_request 
    1.请求来的时候需要经过每一个中间件里面的process_request方法
    结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
    2.如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
    3.如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行
    而是直接原路返回(校验失败不允许访问...)
    process_request方法就是用来做全局相关的所有限制功能

2.process_response 请求走的时候效验
process_response
    1.响应走的时候需要经过每一个中间件里面的process_response方法
    该方法有两个额外的参数request,response
    2.该方法必须返回一个HttpResponse对象
        1.默认返回的就是形参response 因为response就是后端返回给前端的内容,不然报错
        2.你也可以自己返回自己的
    3.顺序是按照配置文件中注册了的中间件从下往上依次经过
![image](https://img2022.cnblogs.com/blog/2608805/202203/2608805-20220320233030548-1869094438.png)
个

3.研究(process_request方法就已经返回了HttpResponse对象):
如果在第一个process_request方法就已经返回了HttpResponse对象,那么响应走的时候是经过所有的中间件里面的process_response还是有其他情况?
答案: 是其他情况

解析:
	就是会直接走同级别的process_response返回

4.flask与django中间件两者区别
flask框架也有一个中间件但是它的规律
只要返回数据了就必须经过所有中间件里面的类似于process_response方法
5.process_view(了解)
执行时间:
1.路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该方法
2.顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
作用:
    在执行某一个视图函数之前,可以在process_view里面做一些零时的额外操作。	

6.process_template_response
触发时间:
1.返回的HttpResponse对象有render属性的时候才会触发
2.顺序是按照配置文件中注册了的中间件从下往上依次经过

7.process_exception
1.当视图函数中出现异常的情况下触发
2.顺序是按照配置文件中注册了的中间件从下往上依次经过

五:实战案例自定义中间件

  • mymiddleware.mydd.py
# 导入MiddlewareMixin
from django.utils.deprecation import MiddlewareMixin

from django.shortcuts import HttpResponse


# 自定义中间件1
class MyMiddleware1(MiddlewareMixin):
    def process_request(self, request):
        print(\'我是第一个自定义process_request方法\')


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

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

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

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

# 自定义django中间件2
class MyMiddleware2(MiddlewareMixin):
    def process_request(self, request):
        print(\'我是第二个自定义process_request方法\')

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

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

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


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

八:模块importlib

1.需求
a.py不使用导入b.py的功能拿到b.py
2.模块importlib
1.作用于字符串的导入,内部按照字符串的点分割成导入文件的形式。
2.缺陷 该方法最小单位只能到py文件名
3.使用
import importlib

res = \'myfile.b\'
ret = importlib.import_module(res)  # from myfile import b
print(ret)

只能拿到b.py的对象
# <module \'myfile.b\' from \'D:\\\\计算机知识存储\\\\中间件\\\\myfile\\\\b.py\'>

七:自定制settings中间件

1.需求
实现用户一点击发送,公司内所有的QQ,微信,邮箱,都收到信息。
  • notify相当于包所以需要__init__

  • notify文件夹

2.init.py

import settings

import importlib

def send_all(content):
    # path_str = 就是 一个一个settings内的字符串 \'notify.email.Email\'
    for path_str in settings.NOTIFY_LIST:
        # rsplit从右往左切 只切一次
        module_path, class_name = path_str.rsplit(\'.\', maxsplit=1)
        # module_path = \'notify.email\'  class_name = \'Email\'  都是字符串的形式

        # 1.利用字符串导入模块
        module = importlib.import_module(module_path)
        # 相当于在导模块  form notify import email

        # 2.利用反射获取类名
        cls = getattr(module, class_name)
        # 拿到真正的类的名字  Email  QQ  Wechat

        # 3.生成类的对象
        obj = cls()
        # 4.利用鸭子类型调用send方法
        obj.send(content)
# QQ.py
class QQ(object):
    def __init__(self):
        pass  # 发送微信需要做的前期准备工作

    def send(self, content):
        print(\'qq通知:%s\' % content)
        
# email.py
class Email(object):
    def __init__(self):
        pass  # 发送邮箱需要做的前期准备工作

    def send(self, content):
        print(\'邮箱通知:%s\' % content)

# wechat.py
class Wechat(object):
    def __init__(self):
        pass  # 发送微信需要做的前期准备工作

    def send(self, content):
        print(\'微信通知:%s\' % content)

settings.py

NOTIFY_LIST = [
    \'notify.email.Email\',
    \'notify.qq.QQ\',
    \'notify.wechat.Wechat\'
]

start.py

import notify
notify.send_all(\'快下课了\')

以上是关于什么是django中间件?(七个中间件-自定义中间件)的主要内容,如果未能解决你的问题,请参考以下文章

django中间件

Django--中间件

django中间件

django中间件

19 Django中间件

Django之中间件