django中间件

按照django流程来算,中间件(MIDDLEWARE)位于第二个,根据位置可以大概知道它是第一关,也就是请求过来之后先经过它,然后才往下执行,根据这个特性,能够知道它和防火墙差不多,提到防火墙,那么就应该知道一些简单的知识,没错:

你符合我的要求,我才让你通过;

如果需要统计什么,可以在我这设置(日志);

全局操作;

总之,我能想到只有这些,这些一般也够了,所以先看它是什么样的,打开你django项目中的settings文件,然后在里面找一个

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',

'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] django1.0以上版本,是这种格式 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.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]

它的流程是这样的(https://docs.djangoproject.com/en/1.8/topics/http/middleware/)

根据上图可以看出,中间件的每一步都要有一个值,比如进来的时候是process_request,出去的时候是process_response,懵了?看下面

中间件就是一层层的"防火墙",当请求到来之后会逐一的经过"每道墙",然后如果有一道墙执行了return,那么请求将不会往下执行,直接返回出去;
如果请求进来的时候没有遇到return,那么它会执行到底,直到把所有的代码执行完之后,才会返回出去;

一句话概括:我要去厕所,没人拦我,我直接蹲坑,如果有人拦我,我直接离开!

理论部分先到这,接下来说如何去写:

首先新建一个.py文件,然后大概格式是这样

然后在这个文件里随便写几个类,下见代码:

"""
我的django没有MiddlewareMixin这个类,所以使用的时候先要定义一个,
如果你的有,可以直接
from django.utils.deprecation import MiddlewareMixin
这样去调用
"""
class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

class Row1(MiddlewareMixin):
    def process_request(self,request):
        print("中间件1请求")
    def process_response(self,request,response):
        print("中间件1返回")
        return response

class Row2(MiddlewareMixin):
    def process_request(self,request):
        print("中间件2请求")
        # return HttpResponse("走")
    def process_response(self,request,response):
        print("中间件2返回")
        return response

class Row3(MiddlewareMixin):
    def process_request(self,request):
        print("中间件3请求")
    def process_response(self,request,response):
        print("中间件3返回")
        return response
中间件

然后把这个文件添加到settings文件里

然后启动服务,你会看到

可以看得出来中间件的顺序,如何知道它是先执行的呢?你可以在视图函数中打印一个东西,如下代码

#!/usr/bin/env python
# -*- coding: utf-8 -*- 
__Author__ = 'Chen Chen'

from django.shortcuts import HttpResponse,render

def server(request):
    # return HttpResponse("this is server")
    print("这是 视图函数") # 添加
    return render(request, "server.html")

然后启动服务,你会发现

 这就证明了,中间件是在视图函数前执行的,当django流程执行完毕之后,他又返回出去,这就是中间件的作用。一般情况下,中间件用于全局操作,比如说黑白名单,比如说日志,比如说统计等等,均可以在中间件内实现。

根据官网得知,中间件还有一些其他的操作:

https://docs.djangoproject.com/en/1.8/topics/http/middleware/

官网给出的五种方法,第一个和第四个已经知道了,接下来看其他的
rocess_request(request) # 已知
process_view(request, view_func, view_args, view_kwargs)
process_template_response(request, response)
process_response(request, response) # 已知
process_exception(request, exception)

 首先说

process_view(request, view_func, view_args, view_kwargs)

根据命名可以得知它是和视图相关的,那么如何操作呢?看代码

settings:
MIDDLEWARE_CLASSES = [
    .........................
    'my_django.mid.Row1', # 添加
]

views:
from django.shortcuts import HttpResponse,render

def server(request):
    # return HttpResponse("this is server")
    return render(request, "server.html")
from . views import server
"""
我的django没有MiddlewareMixin这个类,所以使用的时候先要定义一个,
如果你的有,可以直接
from django.utils.deprecation import MiddlewareMixin
这样去调用
"""
class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

class Row1(MiddlewareMixin):
    """官网提示
    process_view(request, view_func, view_args, view_kwargs)
    """
    def process_view(self,request, view_func, view_args, view_kwargs):
        print("这是来自于视图函数的内容%s"%server(request))
        return

 

改完之后,运行程序,你会发现它执行了视图函数,通过打印可以得知,它把你视图函数里面的功能加了进来,这样就相当于你定义了个函数,然后在它里面执行

 所有中间件都是这样操作的。

接下来看

process_exception(request, exception)

同样可以看出它是和错误相关的

views:
from django.shortcuts import HttpResponse,render

def server(request):
    # return HttpResponse("this is server")
    print("视图函数")
    int('sssdsfdfdf') # 模拟报错
    return render(request, "server.html")

mid:
from django.shortcuts import HttpResponse
"""
我的django没有MiddlewareMixin这个类,所以使用的时候先要定义一个,
如果你的有,可以直接
from django.utils.deprecation import MiddlewareMixin
这样去调用
"""
class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response


class Row1(MiddlewareMixin):
    """官网提示
    process_exception(request, exception)
    """
def process_exception(self,request, exception): return HttpResponse("你的视图函数报错了,我的process_exception替你把错误捕获了")

 由此可以知道,它是专门为我们捕获视图错误的,既然可以返回字符串,那么同样也可以返回其他的实体页面(它。。如果你的视图函数没有报错,它是不执行的)

接下来还有一个

process_template_response(request, response)

模板,接下来看使用方法:

views:

from django.shortcuts import HttpResponse

class Foo():
    def __init__(self,chen):
        self.chen=chen
    def render(self):
        return HttpResponse('这是类的返回值')

def server(request):
    print("这是函数的返回值")
    obj=Foo(request)
    return obj

mid:
"""
我的django版本开始有点问题,我撞了1.0,可以直接调用中间件
"""
from django.utils.deprecation import MiddlewareMixin # 直接调用

class Row1(MiddlewareMixin):
    """官网给出
    process_template_response(request, response)
    """
    def process_template_response(self,request, response):
        print("ok")
        return response

 执行上面的结果可以看到

记住关键字:这个process_template_response(self,request, response)只有你的视图中有render函数(实际叫方法)才会执行,你会问,为什么单独的一个render函数无法执行?首先要明白什么叫方法,方法不就是类里面的函数吗?如果你单独一个函数,它不会认为你这是是一个方法,所以在中间件里面它默认的不执行,就像错误捕获一样,你带吗没报错,它就不会执行,别问为什么,因为源码就这样,如果想研究,可以自行研究!

所以说:在定义中间件的时候,常用的两种,也可以是全部用上,这没有硬性规定,只有看需求,一般如果要是都用,那么格式就是完整的,也就是带着五中方法全写上,这样比较好,也不好,还是那句废话:看需求!

 

posted on 2018-06-15 11:34  ArkhamKnight  阅读(73)  评论(0)    收藏  举报

导航