学习笔记,仅供参考,有错必究
文章目录
- 中间键Middleware
- 中间件类
- 编写中间键
- 举个例子
中间键Middleware
中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的插件系统(拥有插件可以增加功能,没有插件也不影响使用),用于全局改变 Django 的输入(请求)或输出(响应)。
每个中间件组件负责做一些特定的功能。例如,中间件组件 AuthenticationMiddleware,它利用会话将用户与请求关联起来。
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',
]
中间件类
中间键必须继承自django.utils.deprecation.MiddlewareMixin类
中间件类必须实现下列五个方法中的一个或多个:
- def process_request(self, request)
- 在每个请求上调用,在执行视图处理之前被调用,返回None或HttpResponse对象,若返回为None,则继续调用视图处理函数,如果返回为HttpResponse对象,则不必调用视图处理函数。
- def process_view(self, request, callback, callback_args, callback_kwargs)
- 在每个请求上调用,在执行视图处理之前被调用,返回None或HttpResponse对象
- def process_response(self, request, response)
- 在每个请求上调用,在所有响应返回浏览器之前被调用,返回的一定是HttpResponse对象
- def process_exception(self, request, exception)
- 当处理过程中抛出异常时调用,返回一个HttpResponse对象
- def process_template_response(self, request, response)
- 在每个请求上调用,在视图刚好执行完毕之后被调用,返回实现了render方法的响应对象
注意, 中间件中的大多数方法在返回None时,表示忽略当前操作进入下一项事件,当返回HttpResponese对象时,表示此请求结束,直接返回给客户端。
编写中间键
from django.http import HttpResponse, Http404
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
print("中间件方法 process_request 被调用")
#在浏览器与url管理器之间拦截
def process_view(self, request, callback, callback_args, callback_kwargs):
print("中间件方法 process_view 被调用")
#在url管理器之间与视图之间拦截
def process_response(self, request, response):
print("中间件方法 process_response 被调用")
return response
#视图到浏览器之间
def process_exception(self, request, exception):
print("中间件方法 process_exception 被调用")
def process_template_response(self, request, response):
print("中间件方法 process_template_response 被调用")
return response
我们编写完中间键之后,还需要对中间键进行注册(标记中间键的位置):
# file : settings.pyMIDDLEWARE = [
...
'middleware.mymiddleware.MyMiddleWare',
]
举个例子
现在,我们基于以前的Blog制作图书管理系统里的项目,我们编写一个中间键,让没有登录的用户不能访问书库(访问就报出404),登录的用户可以访问书库。
我们在项目下新建一个文件夹mymiddleware,专门放中间键,在这个文件夹下我们创建一个checklogin.py文件:
现在,我们编写这个中间键:
from django.http import HttpResponsefrom django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
print("中间件MyMiddleWare.process_request方法被调用")
return None
再对这个中间键进行注册:
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',
'mymiddleware.checklogin.MyMiddleWare',
]
注意中间键的格式为文件夹名.模块名.类名
现在,我们开启服务,并向主页http://127.0.0.1:8000/发起请求,并查看cmd界面:
June 24, 2020 - 00:13:50Django version 2.2.13, using settings 'mywebsite_bookstore.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
中间件MyMiddleWare.process_request方法被调用
[24/Jun/2020 00:13:54] "GET / HTTP/1.1" 200 368
可以看到,我们在向主页/发起请求之前,中间键就开始被调用了。
现在,我们更改一下我们的中间键:
class MyMiddleWare(MiddlewareMixin):def process_request(self, request):
print("中间件MyMiddleWare.process_request方法被调用")
return HttpResponse("<h2>请求被拦截</h2>")
我们向主页http://127.0.0.1:8000/发起请求:
再向404测试页面http://127.0.0.1:8000/test404/发起请求:
可以看到,当我们设置中间键返回HttpResponse对象后,我们的请求就无法到达视图。
现在,我们加一个判断,如果用户没用登录,就访问书库(即调用bookstore应用下的视图函数),页面会自动跳转到登录页面(/userinfo/login/);如果登录了,就可以直接访问书库:
from django.http import HttpResponsefrom django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
import re
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
print("中间件MyMiddleWare.process_request方法被调用")
if re.match(r'^/bookstore/', request.path_info) \
and ('userinfo' not in request.session):
return HttpResponseRedirect('/userinfo/login')
return None
注意,request.path_info可以拿到请求的路由信息。
现在,我们在未登录状态下向主页http://127.0.0.1:8000/发起请求:
我们点击查看全部图书,可以看到页面跳转到了登录页面:
现在,我们进行登录,并回到主页:
点击查看全部图书:
可以看到,当我们登录之后,就可以访问书库了。