Django中间件

什么是Django的中间件

中间件就是在视图函数执行前后做一些额外的操作,本质就是一个自定义的,类中定义几个方法,用来在全局范围内处理请求和响应,在特定的时间去执行这些方法。

介于请求和响应之间的一道处理过程

Django的中间件执行顺序按settings.py中MIDDLEWARE注册自上而下执行

Django的默认中间件

django中默认有七个中间件,并支持用户自定义五个方法

只要想做一些网站的全局性功能,都应该考虑使用django的中间件,比如:

  1. 全局的用户登录校验
  2. 全局的用户访问频率校验
  3. 全局的用户权限校验
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',
]

img

支持用户自定义的五个方法

img

img

# 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

  1. 请求来的时候会按照settings配置文件中自上而下的顺序依次执行每个中间件内部定义的process_request方法

  2. 如果中间件内部没有该方法,直接跳过执行下一个中间件

  3. 该方法一旦返回了HttpResponse对象,那么请求会立刻停止,原路返回

process_response

  1. 给客户端响应的时候会按照settings配置文件中自下而上的顺序依次执行每一个中间件内部定义的process_response方法
  2. 该方法必须有两个形参,并返回response形参,不返回报错
  3. 该方法如果返回HttpResponse对象,则前端就能获取什么结果,相当中间件修改了原本的数据。

了解即可:

process_view

  1. 路由匹配成功之后执行视图函数之前 会触发
  2. 如果该方法返回了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',

]
posted @ 2019-12-04 21:40  GeminiMp  阅读(171)  评论(0编辑  收藏  举报