144.中间件的原理和定义方式详解

中间件

中间件是在request和response处理过程中的一个插件。比如request到达视图四千,我们可以定义中间件来做一些相关的事情,比如可以判断这个用户有没有登录,如果登录了,就绑定一个对象到request上,也可以在response到达浏览器之前,做一些相关的处理,比如想要统一在response上设置一些cookie信息等。

自定义中间件

中间件所处的位置没有规定,只要是放到项目中即可,一般可以分为两种情况,如果中间件是属于某个app的,那么就可以在这个app下面创建一个python文件用来存储这个中间件,也可以专门创建一个python包,用来存放本项目的所有中间件。创建中间件有两种方式,一种是使用函数,一种是使用类。

1.定义中间件函数

(1)在APP中创建一个python文件,定义与该APP相关的中间件。如果我们想要自己定义的中间件,被django在执行操作的时候使用的话,就要在项目的settings.py文件中的MIDDLEWARE中添加appname.pythonfilename.functionname。函数定义示例代码如下:
from .models import User

def front_user_middlewares(get_response):
    print('front_user_middleware初始化执行的代码....')
    
    def middleware(request):
        print('request到达view视图之前执行的代码....')
        <!--1.在request到达view视图之前,对用户是否进行登录进行判断,如果登录了就在request上绑定一个对象front_user-->
        <!-因为python是一个动态执行的语言,即使在对象已经创建完成,也可以对对象随时绑定属性。-->
        
        <!--首先通过session中是否含有一个sessionid,如果有的话,就认为,该用户已经登录了。-->
        user_id = request.session.get('user_id')
        <!--判断如果user_id存在将执行什么操作,但是这种情况下,同时也存在着user_id不存在的情况,所以我们可以通过try...except...来实现。-->
        if user_id:
            try:
                front_user = User.objects.get(pk=user_id)
                request.front_user = front_user
                print(request.front_user.username)
            except:
                request.front_user = None
        request.front_user = None
        
        <!--执行get_response(request),就相当于转去执行视图函数了,这一点可以通过在相应的视图函数:print(”这是视图函数中执行的代码“),进行验证-->
        response = get_response(request)
        print('response到达浏览器之前执行的代码....')
        
        return response
        
    return middleware
在middleware()函数之前的代码是运行该项目之后就会加载的,而middleware()函数中的代码是只有访问网站的时候才会执行的。
(2)之后我们就可以在视图函数中直接使用request上的front_user对象了,示例代码如下:

def index(request):
    print("这是index view中的代码")
    if request.front_user:
        print(request.front_user.username)
    return render(request, 'index.html')


def my_list(request):
    print('这是my_list中的代码')
    if request.front_user:
        print(request.front_user.username)
    return HttpResponse('success!')

2.定义中间件的类

(1)要想让我们定义的中间件的类起作用的话,同样也需要在settings.py中的MIDDLEWARE中添加appname.pythonfilename.classname。比如,我们想要在request达到view视图函数之前判断用户是否登录,若登录了,就在request上绑定一个front_user对象并且该对象就是新登录的用户。若没有登录,同样为request绑定一个front_user对象,此时就设置为None。示例代码如下:
# 2. 定义一个类
from .models import User

class FrontUserMiddleware(object):

    def __init__(self, get_response):
        print('front_user_middleware初始化执行的代码....')
        <!--需要先保存get_response,以后会用到-->
        self.get_response = get_response

    def __call__(self, request):
        print('request到达view之前执行的代码....')
        user_id = request.session.get('user_id')
        if user_id:
            try:
                front_user = User.objects.get(pk=user_id)
                request.front_user = front_user
                print(request.front_user.username)
            except:
                request.front_user = None
        request.front_user = None
        
        <!--执行get_response()函数就会转去执行view视图函数-->
        response = self.get_resonse(request)
        print('response到达浏览器之前执行的代码....')
        return response

3.即将被遗弃的中间件的定义方式,示例代码如下:

from django.utils.deprecation import MiddlewareMixin
from .models import User


class FrontUserMiddlewareMixin(MiddlewareMixin):

    def __init__(self, get_response):
        self.get_response = get_response
        print('front_user_middleware进行初始化执行的代码....')

    # 1. 定义request到达view视图之前执行的操作
    def process_request(self, request):
        print("request到达view视图之前执行的操作...")
        user_id = request.session.get('user_id')
        if user_id:
            try:
                front_user = User.objects.get(pk=user_id)
                request.front_user = front_user
                print(request.front_user.username)
            except:
                request.front_user = None

        request.front_user = None


    # 2. 定义response到达浏览器之前执行的操作
    def process_response(self, request, response):
        print('response到达浏览器之前执行的操作...')
        return response
posted @ 2020-02-23 22:18  一笑而过~一笑奈何  阅读(439)  评论(0编辑  收藏  举报