Django中间件
什么是Django的中间件
中间件就是在视图函数执行前后做一些额外的操作,本质就是一个自定义的类,类中定义几个方法,用来在全局范围内处理请求和响应,在特定的时间去执行这些方法。
介于请求和响应之间的一道处理过程
Django的中间件执行顺序按settings.py中MIDDLEWARE注册自上而下执行
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',
]
支持用户自定义的五个方法
# coding=utf-8
# File : mymdd.py
# Author: Jack秦
# Date : 2019/12/4
app01/mymiddleware/mymdd.py:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,render,HttpResponse
'''
共同点:如果某个中间件中没有某个方法则会跳过执行下一个中间件
不同点:
process_request:当请求来的时候会触发,若有HttpResponse对象,则立马返回,不会执行后面的中间件
process_response:当请求走的时候会触发,若有HttpResponse对象,则会篡改视图函数返回的数据
process_view:当路由匹配成功之后 视图函数执行之前 触发,若有HttpResponse对象,则立马返回,不会执行后面的视图函数
process_exception:当返回的对象有错误后会触发
process_request(self,request) 方法总结:该方法有一个形参:request
1. 请求来的时候按照settings配置的中间件 自上而下 顺序执行 中间件中的 process_request 方法
2. 如果某个中间件中没有该方法则会跳过执行下一个中间件
3. 如果某个中间件中该方法返回了HttpResponse对象,会立即返回HttpResponse对象不再执行下面的中间件
process_response(self,request,response) 方法总结:该方法有两个形参:request response,必须返回 形参response
1. 请求完成给客户端响应的时候按照settings配置的中间件 自下而上 顺序执行 中间件中的 process_response 方法
2. 如果某个中间件中没有该方法则会跳过执行下一个中间件
3. 如果某个中间件中该方法返回了HttpResponse对象,则前端获取到的结果就是这个中间件的
process_response 方法二次处理后的结果
process_view(self, request, view_name, *args, **kwargs) 方法总结:该方法有两个形参:request view_name(视图函数的内存地址)
1. 在路由匹配成功之后 视图函数执行之前 执行 process_response 方法
2. 如果某个中间件中没有该方法则会跳过执行下一个中间件
3. 如果某个中间件中该方法返回了HttpResponse对象,则前端获取到的视图函数的结果就是这个中间件返回的结果
process_exception(self, request, exception) 方法总结:该方法有两个形参:request exception(异常信息)
当返回的对象中出现错误后 会按照settings配置文件中自下而上的顺序执行
process_template_response(self, request, response) 方法总结: 该方法有两个形参:request response
当返回的对象中含有render属性指向了一个render方法的时候自下而上的触发
def render():
return HttpResponse('你好呀 我是奇葩')
obj = HttpResponse('我很好')
obj.render = render
return obj
'''
class MyMdd1(MiddlewareMixin):
def process_request(self,request):
print('我是第一个中间件的process_request方法')
# return HttpResponse('我是第一个中间件的process_request方法')
def process_response(self,request,response):
print('我是第一个中间件的process_response方法')
return response
def process_view(self, request, view_name, *args, **kwargs):
print('我是第一个中间件的process_view方法')
def process_exception(self, request, exception):
print('我是第一个中间件的process_exception方法')
def process_template_response(self, request, response):
print('我是第一个中间件里面的奇葩方法')
return response
class MyMdd2(MiddlewareMixin):
def process_request(self,request):
print('我是第二个中间件的process_request方法')
def process_response(self,request,response):
print('我是第二个中间件的process_response方法')
return response
# return HttpResponse('我是第二个中间件的process_response方法')
def process_view(self, request, view_name, *args, **kwargs):
# print('view_name',view_name)
print('我是第二个中间件的process_view方法')
# return HttpResponse('我是第二个中间件的process_view方法')
def process_exception(self, request, exception):
print('我是第二个中间件的process_exception方法')
def process_template_response(self, request, response):
print('我是第二个中间件里面的奇葩方法')
return response
共同点:
如果某个中间件中没有某个方法则会跳过执行下一个中间件
不同点:
process_request:当请求来的时候会触发,若有HttpResponse对象,则立马返回,不会执行后面的中间件
process_response:当请求走的时候会触发,若有HttpResponse对象,则会篡改视图函数返回的数据
process_view:当路由匹配成功之后 视图函数执行之前 触发,若有HttpResponse对象,则立马返回,不会执行后面的视图函数
process_exception:当返回的对象有错误后会触发
需要掌握:
process_request
-
请求来的时候会按照settings配置文件中自上而下的顺序依次执行每个中间件内部定义的process_request方法
-
如果中间件内部没有该方法,直接跳过执行下一个中间件
-
该方法一旦返回了HttpResponse对象,那么请求会立刻停止,原路返回
process_response
- 给客户端响应的时候会按照settings配置文件中自下而上的顺序依次执行每一个中间件内部定义的process_response方法
- 该方法必须有两个形参,并返回response形参,不返回报错
- 该方法如果返回HttpResponse对象,则前端就能获取什么结果,相当中间件修改了原本的数据。
了解即可:
process_view
- 路由匹配成功之后执行视图函数之前 会触发
- 如果该方法返回了HttpResponse对象,则自下而上经过每一个中间件里面的process_response方法
process_template_response
当返回的对象中含有render属性指向了一个render方法的时候自下而上的触发,
process_exception
当视图函数中出现错误会自下而上自动触发
Django请求生命周期
自定义中间件登录验证
中间件版的登录验证需要依靠session,所以数据库种要有django_session表。
urlls.py
from app02 import views as v2
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/',v2.login),
url(r'^home/',v2.home),
url(r'^index/',v2.index)
]
views.py
from django.shortcuts import render,redirect,HttpResponse
from app02 import models
# Create your views here.
def login(request):
error_msg=''
if request.method=='POST':
username=request.POST.get('username')
password=request.POST.get('password')
user_obj=models.User.objects.filter(username=username,password=password)
if user_obj:
#设置session
request.session['login']='ok'
#获取用户想直接访问的URL
url=request.GET.get('next')
#如果有,就跳转到客户初始想访问的URL
if not url:
#没有则默认跳转到home页面
url='/home/'
return redirect(url)
else:
error_msg='username or password error!'
return render(request,'login.html',{'error_msg':error_msg})
def home(request):
return HttpResponse('<h1>这是home页面 只有登录了才能看到</h1>')
def index(request):
return HttpResponse('<h1>这是index页面 也只有登录了才能看到<h1>')
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆页面</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<label for="">username:<input type="text" name="username"></label>
<label for="">password:<input type="password" name="password"></label>
<input type="submit" value="submit">
</form>
<h1 style="color: red">{{ error_msg }}</h1>
</body>
</html>
middlewares.py:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect
class Check_Login(MiddlewareMixin):
def process_request(self,request):
next_url=request.path_info
if not next_url.startswith('/login/'):
is_login=request.session.get('login','')
if not is_login:
return redirect('/login/?next={}'.format(next_url))
在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',
'middleware.my_middleware.Check_Login',
]