Django中间件简单说明

中间件

配置文件

项目主目录中的配置文件是django留给开发者使用的用户级别配置文件

实际上django有一个自己的默认全局配置文件。

那么他们的关系如下

# django默认配置
from django.conf import global_settings

# 用户级别配置
from django_middleware import settings


from django.conf import settings # 中间人
# 比如需要引入配置中的某个配置项settings.APPEND_SLASH,那么这样的引入的查找顺序是这样,先去用户级别settings.py文件中去找这个配合,
如果没有找到,那么会去global_settings中去找默认配置

 

django请求生命周期

 

 

(1)过程描述

第一步:浏览器发起请求
第二步:WSGI创建socket服务端,接收请求(Httprequest)
第三步:中间件处理请求
第四步:url路由,根据当前请求的URL找到视图函数
第五步:view视图,进行业务处理(ORM处理数据,从数据库取到数据返回给view视图;view视图将数据渲染到template模板;将数据返回)
第六步:中间件处理响应
第七步:WSGI返回响应(HttpResponse)
第八步:浏览器渲染

 

 中间件用来对请求和响应做一些统一加工和处理的,比如对所有请求中的post请求做一个csrftoken认证,就用到了我们的'django.middleware.csrf.CsrfViewMiddleware',后面视图中能够使用request.session做一个session相关操作,这个request.session的功能就是在这个中间件中加工好的'django.contrib.sessions.middleware.SessionMiddleware',

 

自定义中间件: 登录认证、权限认证、频率访问限制,请求数据统计...

自定义中间件的步骤

1 在应用文件夹下面创建一个文件夹,名字随便,比如叫做mymiddleware

2 在mymiddleware文件夹下面创建一个py文件,名称随意,比如叫做middlewares.py

3 在middlewares.py文件中写上如下内容

4 在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',
    'app01.mymiddleware.middelwares.LoginAuth',
]

# 配置中间件类,告诉django,我写的这个自定义中间件,你帮我使用上,一般都放到最后,不然上面几个中间件的相关功能就没办法使用上了
'app01.mymiddleware.middlewares.LoginAuth',
# 如果中间件功能不想用了,就注释它就行了
# 'app01.mymiddleware.middlewares.LoginAuth'

这样几步搞定之后,所有的请求都会触发我们的中间件类中的process_request方法。

登录认证中间件示例

中间件代码如下

# 登录认证中间件
class LoginAuth(MiddlewareMixin):
    # /login/登录请求,应该正常放行,让他能获得login.html页面
    # 白名单、黑名单
    white_list = ['/login/', ]
    def process_request(self,request):
        print('请求来啦!!!')
        # 获取当前请求路径:request.path /home/
        # 如果当前请求的路径在白名单里面,我们不进行登录认证
        if not request.path in self.white_list:

            is_login = request.session.get('is_login')  #True
            if not is_login:
                return redirect('/login/')

视图代码如下

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        uname = request.POST.get('username')
        if uname == 'root':
            request.session['is_login'] = True

            return redirect('/home/')  #告诉浏览器向/home/发送get请求获取页面
        else:
            return redirect('/login/')


def home(request):
    print('home')
    return render(request, 'home.html')


def index(request):
    print('index')
    return render(request, 'index.html')

 

中间件的五个方法

整个中间的执行顺序

 

 

 

 

 

 

方法如下:process_request和process_response这两个是重点

  • process_request(self,request)

  • process_view(self, request, view_func, view_args, view_kwargs)

  • process_template_response(self,request,response)

  • process_exception(self, request, exception)

  • process_response(self, request, response)

针对这个五个方法,我们来看看这5个方法的执行流程。

1.  process_request

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print('MD1--process_request')
        # 当process_request返回的是None,那么才会继续执行后面的中间件的process_request,如果你是最后一个中间件,
      并且你返回的是None,那么逻辑会继续执行到我们的url路由控制器
# 但是当process_request里面return的是一个HttpResponse对象,那么后面的中间件的process_request将不再执行,也不会走到url路由控制器 return HttpResponse('中间件md1的逻辑,没有通过!!!!') class Md2(MiddlewareMixin): def process_request(self, request): print('MD2--process_request')

2 process_response

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print('MD1--process_request')
        # 当process_request返回的是None,那么才会继续执行后面的中间件的process_request,
      如果你是最后一个中间件,并且你返回的是None,那么逻辑会继续执行到我们的url路由控制器
# 但是当process_request里面return的是一个HttpResponse对象,那么后面的中间件的process_request将不再执行,也不会走到url路由控制器 return HttpResponse('中间件md1的逻辑,没有通过!!!!') def process_response(self, request, response): ''' :param request: 当前请求对象 :param response: 视图函数的响应对象 :return: ''' print('Md1--响应') # print(response) #<HttpResponse status_code=200, "text/html; charset=utf-8"> # 对响应内容做统一处理 # response['xx'] = 'oo' #统一加响应头 # print(response.content) #b'ok' # 注意,如果你写了process_response方法,那么这个方法必须return response return response class Md2(MiddlewareMixin): def process_request(self, request): print('MD2--process_request') def process_response(self, request, response): print('Md2--响应') # if response.content != b'ok': # 如果process_response方法里面return了一个HttpResponse对象,这个对象会覆盖视图返回来的HttpResponse对象 # return HttpResponse('响应不ok!!!') return response

注意:当中间件1的process_request方法return的是一个HttpResponse对象,那么会执行中间件1的process_response方法,不会去执行中间件2 的方法了

 

 

 

 3 process_view(self, request, view_func, view_args, view_kwargs):

示例代码

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print('MD1--process_request')
        # return HttpResponse('中间件md1的逻辑,没有通过!!!!')

    def process_response(self, request, response):

        print('Md1--响应')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('md1---view')

class Md2(MiddlewareMixin):

    def process_request(self, request):
        print('MD2--process_request')

    def process_response(self, request, response):
        print('Md2--响应')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        '''

        :param request:
        :param view_func:   此次请求要执行的视图函数对象
        :param view_args:  要函数的参数
        :param view_kwargs: 要函数的参数
        :return:
        '''
        print('md2---view')
        # print(view_func, view_args, view_kwargs)
        print(view_func.__name__) # home

 

 

 

 

4 process_exception(self, request, exception)

是当试图函数出现错误或者异常时,自动触发执行的方法,能够捕获试图出现的错误,进行一些错误的统一处理

示例代码

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print('MD1--process_request')
        # return HttpResponse('中间件md1的逻辑,没有通过!!!!')

    def process_response(self, request, response):

        print('Md1--响应')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('md1---view')

    def process_exception(self, request, exception):
        print('md1--exception')

class Md2(MiddlewareMixin):

    def process_request(self, request):
        print('MD2--process_request')

    def process_response(self, request, response):
        print('Md2--响应')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        '''

        :param request:
        :param view_func:   此次请求要执行的视图函数对象
        :param view_args:  要函数的参数
        :param view_kwargs: 要函数的参数
        :return:
        '''
        print('md2---view')
        # print(view_func, view_args, view_kwargs)
        # print(view_func.__name__) # home

    def process_exception(self, request, exception):
        
        from django.core.exceptions import PermissionDenied
        # print('>>>>>>', exception, type(exception))
        # if isinstance(exception,PermissionDenied):
        #     return HttpResponse('权限不够!!!!!')
        #>>>>>> 权限不够 <class 'django.core.exceptions.PermissionDenied'>
        # >>>>>> 出错啦!!!
        print('md2--exception')

视图函数示例

from django.core.exceptions import PermissionDenied

def home(request):
    print('home')
    # raise Exception('出错啦!!!')
    raise PermissionDenied('权限不够')
    return render(request, 'home.html')

 

 

5 process_template_response(self,request,response)

代码示例

from django.shortcuts import render, redirect, HttpResponse
from django.utils.deprecation import MiddlewareMixin


class Md1(MiddlewareMixin):

    def process_request(self,request):
        print('MD1--process_request')
        # return HttpResponse('中间件md1的逻辑,没有通过!!!!')

    def process_response(self, request, response):

        print('Md1--响应')
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('md1---view')

    def process_exception(self, request, exception):
        print('md1--exception')

    def process_template_response(self, request, response):
        print("MD1 中的process_template_response")
        return response

class Md2(MiddlewareMixin):

    def process_request(self, request):
        print('MD2--process_request')

    def process_response(self, request, response):
        print('Md2--响应')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('md2---view')

    def process_exception(self, request, exception):

        print('md2--exception')

    def process_template_response(self, request, response):
        print("MD2 中的process_template_response")
        return response

视图代码

def home(request):
    print('home')
    def render():
        print('你好render')
        return HttpResponse('你好response')

    ret = HttpResponse('ojbk')
    # 必须给HttpResponse对象封装一个render属性等于一个render函数,才能出发中间件里面的process_template_response方法
    ret.render = render
    return ret

 

posted on 2020-07-28 16:17  fdsimin  阅读(124)  评论(0编辑  收藏  举报