我们首先来看一下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',
]
# SessionMiddleware代码
class SessionMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
self.get_response = get_response
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore
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):
"""
If request.session was modified, or if the configuration is to save the
session every time, save the changes and set a session cookie or delete
the session cookie if the session has been emptied.
"""
return response.
# 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
# AuthenticationMiddleware代码
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
assert hasattr(request, 'session'), (
"The Django authentication middleware requires session middleware "
"to be installed. Edit your MIDDLEWARE%s setting to insert "
"'django.contrib.sessions.middleware.SessionMiddleware' before "
"'django.contrib.auth.middleware.AuthenticationMiddleware'."
) % ("_CLASSES" if settings.MIDDLEWARE is None else "")
request.user = SimpleLazyObject(lambda: get_user(request))
# 我们看到每个中间件基本上都是有process_request和process_response方法,如果没有就直接跳过,
# 'django.contrib.sessions.middleware.SessionMiddleware',其实就是这个中间件的路径,需要查看源码只需要from django.contrib.sessions.middleware import SessionMiddleware就可以了。
# 注意:
'''
process_response一般传入两个参数,request和response
return response
'''
# 下面我们来讲讲自定义中间件该怎么写
django支持程序员自定义中间件并且暴露五个可以自定义的方法
# 掌握
process_request
process_response
# 了解
process_view
process_exception
process_template_response
如何定义中间件
1.在项目名或者应用名下创建任意一个文件夹
2.在文件夹中创建一个任意名的py文件
3.在py文件中书写类(这个类必须继承MiddlewareMixin)
然后在类里面可以自定义五个方法
4.需要将类的路径以字符串形式注册到配置文件中才能生效
创建自定义中间件
# 在apps下新建文件custom_middleware,在文件夹下新建文件my_middleware.py
from django.utils.deprecation import MiddlewareMixin
class My_middleware1(MiddlewareMixin):
def process_request(self, request):
print('我是自定义的第一个process_request中间件')
def process_response(self,request, response):
print('我是自定义的第一个process_response中间件')
return response
class My_middleware2(MiddlewareMixin):
def process_request(self,request):
print('我是自定义的第二个process_request中间件')
def process_response(self,request, response):
print('我是自定义的第二个process_response中间件')
return response
# 写完一定要记得在settings.py的MIDDLEWARE = [...]中写入路径,以字符串的形式
MIDDLEWARE = [
'apps.custom_middleware.my_middleware.My_middleware1',
'apps.custom_middleware.my_middleware.My_middleware2',
]
# view.py中直接一个get请求打印并返回一个数据
from django.shortcuts import HttpResponse
def index(request,*args,**kwargs):
print('我是视图函数')
return HttpResponse('我是视图函数')
# 执行django,控制台得到打印结果
'''
[21/Apr/2021 16:39:04] "GET /index/ HTTP/1.1" 200 18
我是自定义的第一个process_request中间件
我是自定义的第二个process_request中间件
我是视图函数
我是自定义的第二个process_response中间件
我是自定义的第一个process_response中间件
Process finished with exit code 0
'''
# 我们可以看出process_request是请求来的时候执行,从上往下依次执行,而process_response则是从下向上依次执行。还有主要process_response结尾的时候返回了一个response,而process_request并没有return。
# 假入在第一个process_request里返回return会怎么样呢
# 直接返回return None结果还是和上面一样,我们返回点数据试试,其他不变,只加一个return
def process_request(self, request):
print('我是自定义的第一个process_request中间件')
return HttpResponse('hello')
# 执行django,控制台得到打印结果
# 浏览器页面显示hello
'''
我是自定义的第一个process_request中间件
我是自定义的第一个process_response中间件
[21/Apr/2021 16:50:09] "GET /index/ HTTP/1.1" 200 5
'''
# 说明process_request直接返回数据,那么django就直接执行和process_request同级别的process_response,然后返回数据,不会在往下执行了。
# 下面试试process_response,return返回数据
# 假如在第一个process_response里返回return会怎么样呢
# 直接返回return None结果还是和上面一样,我们返回点数据试试,其他不变,只加一个return
def process_response(self,request, response):
print('我是自定义的第一个process_response中间件')
return HttpResponse('hello')
# 执行django,控制台得到打印结果
# 浏览器页面显示hello
'''
[21/Apr/2021 16:54:04] "GET /index/ HTTP/1.1" 200 5
我是自定义的第一个process_request中间件
我是自定义的第二个process_request中间件
我是视图函数
我是自定义的第二个process_response中间件
我是自定义的第一个process_response中间件
'''
# 我们可以看出来,浏览器显示的数据是process_response里面打印的数据,但是控制台打印的是视图函数的数据
下面是了解知识点
# process_view
# 路由匹配成功之后,视图函数执行之前,会自动执行中间件里面的该方法,从上往下。
def process_view(self,request,view_name,*args,**kwargs)
print('...')
# process_exception
# 返回的Http对象由render属性的时候才会触发,从下往上执行。
def process_exception()
print('...')
# process_template_response
# 当视图函数中出现异常的情况下触发,从下往上
def process_template_response(self,request,response):
print('...')
return response
# view.py
def index(request):
obj=HttpResponse('index')
def render():
print('...')
return HttpResponse('执行process_template_response方法')
obj.render = render
return obj