欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

中间件

程序员文章站 2022-05-09 11:09:06
中间件 middleware 中间件的五个方法 定义 settings配置中 登录验证 条件:只有登录成功才能访问各个页面,也就是无论点击哪里都跳转到登录界面 用session时会报一个错误 low版本 装饰器版 views.py 高级版 1.设置自定义中间件 在应用app01中 在应用app01中 ......

中间件 middleware

中间件的五个方法

中间件可以定义五个方法,分别是:(主要的是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)

定义

 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

settings配置中

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',
]
配置的是一个个路径,封装一些功能,相当于
from django.middleware.security import securitymiddleware

登录验证

条件:只有登录成功才能访问各个页面,也就是无论点击哪里都跳转到登录界面

用session时会报一个错误
中间件

low版本 装饰器版

views.py

from django.shortcuts import render,httpresponse,redirect

# create your views here.

def wrapper(f):
    def inner(request,*args,**kwargs):
        status = request.session.get("is_login")
        # 获取session的值,
        if status:
            return f(request,*args,**kwargs)
        else:
            return redirect("login")
    return inner

@wrapper
def home(request):

    return render(request,"home.html")

def login(request):
    if request.method == "get":
        return render(request,"login.html")
    else:
        user = request.post.get("username")
        pwd = request.post.get("password")
        if user == "alex" and pwd == "123":
            request.session["is_login"] = true
            return redirect("home")
        else:
            return redirect("login")

@wrapper
def index(request):
    return render(request,"index.html")

高级版

1.设置自定义中间件

在应用app01中

在应用app01中创建一个包,随便起名字,一般都放在一个叫做utils的包里面,表示一个公用的组件,创建一个py文件,随便起名字,例如叫做:middlewares.py,内容如下

from django.utils.deprecation import middlewaremixin

class loginauth(middlewaremixin):
    #请求来了,自动执行
    def process_request(self,request):
        print("请求来了")

中间件

然后去settings中的middleware中设置中间件地址

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.utils.mymiddleware.loginauth'
]

中间件

django的请求生命周期

中间件

具体解释

  1. 浏览器请求,wsgi.py,它封装这socket,request对象,request对象给中间键,中间件根据middleware封装的中间件一层一层向下执行,自动执行每个中间件中的请求函数

  2. 执行顺序从上到下,例如,我们把自定义的中间件放在session中间件的上边,那么session就不起作用了,所以自定义的中间件是放在最下边位置

  3. 中间件加工完之后,给了url控制器,然后执行视图函数views,视图函数再通过orm与数据库进行交互,并且渲染页面

    注意如果此处没有return值,默认返回的是none,表示正常,向下执行,如果return值是别的值,那么就不会向下执行了,直接执行响应中间件的response方法给浏览器了

  4. 执行完成后,页面需要间数据返还给浏览器,不需要经过url,但是还会经过中间件

  5. 中间件中执行process_response方法

中间件

所以由上引入白名单概念,就是让不需要session的函数先执行,例如login函数

白名单

中间件的py文件中

from django.utils.deprecation import middlewaremixin
from django.shortcuts import render,httpresponse,redirect
class loginauth(middlewaremixin):
    #白名单
    white_list = ["/login/",]
    def process_request(self,request):
        print("请求来了")
        path = request.path
        #获取请求路径
        if path not in self.white_list:
            status = request.session.get("is_login")
            if not status:
                return redirect("login")
        

    def process_response(self,request,response):
        print("响应走了")
        return response

views.py 应用了中间件就不用了装饰器了

from django.shortcuts import render,httpresponse,redirect

# create your views here.

def home(request):
    print("这是home函数")
    return render(request,"home.html")

def login(request):
    if request.method == "get":
        print("这是login函数")
        return render(request,"login.html")
    else:
        user = request.post.get("username")
        pwd = request.post.get("password")
        if user == "alex" and pwd == "123":
            request.session["is_login"] = true
            return redirect("home")
        else:
            return redirect("login")

def index(request):
    print("这是index函数")
    return render(request,"index.html")

在上述代码中,请求白名单中的数据时,根据请求路径判断下列条件的结果,当路径在白名单中的时候,if条件不成立,默认返回none,正常执行views函数,如果访问home函数等,以为没有在白名单中,执行if条件,如果已经有了session值,则默认返回none,正常执行函数,如果没有session,则执行下一个if判断,重定向到login路径,再次请求,执行同上

中间件有多个方法时的执行顺序

settings中

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.utils.mymiddleware.loginauth'
    'app01.utils.mymiddleware.md1',  # 新增中间件
    "app01.utils.mymiddleware.md2",  # 新增中加件
]

views.py

from django.shortcuts import render,httpresponse,redirect

# create your views here.

def home(request):
    print("这是home函数")
    return render(request,"home.html")

def login(request):
    if request.method == "get":
        print("这是login函数")
        return render(request,"login.html")
    else:
        user = request.post.get("username")
        pwd = request.post.get("password")
        if user == "alex" and pwd == "123":
            request.session["is_login"] = true
            return redirect("home")
        else:
            return redirect("login")

def index(request):
    print("这是index函数")
    return render(request,"index.html")

process_resquest 和 process_response 方法顺序

middleware.py 中间件中文件

class md1(middlewaremixin):
    def process_request(self,request):
        #request是一个请求的对象
        print("md1的process_request方法",request)
        #return httpresponse("ok")   ---------------------- 第一知识点  第一执行

    def process_response(self,request,response):
        print("md1的process_response方法",response)
        return response
        #return httpresponse("ok")  ---------------------- 第二知识点  第四执行

class md2(middlewaremixin):
    def process_request(self,request):
        print("md2的process_request方法",request)
        #return httpresponse("ok")  ----------------------- 第三知识点   第二执行

    def process_response(self,request,response):
        print("md2的process_response方法",response)
        #response 接收的是函数的返回值,是一个response对象
        return response
        #return httpresponse("ok")  ---------------------- 第四知识点    第三执行

中间件

有return自定义内容的时候

都是get方法时验证

第一知识点解释

md1的process_request方法 <wsgirequest: get '/index/'>
md1的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
当我们在浏览器发送请求时,执行到中间件时就不再向后执行,只执行返回函数process_response

第二知识点解释

md1的process_request方法 <wsgirequest: get '/index/'>
md2的process_request方法 <wsgirequest: get '/index/'>
这是index函数
md2的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
md1的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
当我们在浏览器发送请求时,由于返回值的位置是最后执行的,所以所有的函数都执行了,但是由于返回的是自定义的,而不是response对象,所以返回页面不是html文件,而是ok

第三知识点解释

md1的process_request方法 <wsgirequest: get '/login/'>
md2的process_request方法 <wsgirequest: get '/login/'>
md2的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
md1的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
当我们在浏览器发送请求时,执行到中间件时就不再向后执行,只执行返回函数process_response,依次向上执行(中间件顺序) 所以返回页面不是html文件,而是ok

第四知识点解释

md1的process_request方法 <wsgirequest: get '/login/'>
md2的process_request方法 <wsgirequest: get '/login/'>
这是login函数
md2的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
md1的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
当我们在浏览器发送请求时,由于返回值的位置是最后执行的,所以所有的函数都执行了,但是由于返回的是自定义的,而不是response对象,所以返回页面不是html文件,而是ok

process_view

middleware.py

class md1(middlewaremixin):
    def process_request(self,request):
        #request是一个请求的对象
        print("md1的process_request方法",request)
        # return httpresponse("ok")

    def process_response(self,request,response):
        print("md1的process_response方法",response)
        return response
        # return httpresponse("ok")

    def process_view(self,request,view_func,view_args,view_kwargs):
        print(view_func)
        print("md1的process_view")

class md2(middlewaremixin):
    def process_request(self,request):
        print("md2的process_request方法",request)
        # return httpresponse("ok")

    def process_response(self,request,response):
        print("md2的process_response方法",response)
        #response 接收的是函数的返回值,是一个response对象
        return response
        # return httpresponse("ok")

    def process_view(self,request,view_func,view_args,view_kwargs):
        print(view_func)
        print("md2的process_view")

index请求结果

md1的process_request方法 <wsgirequest: get '/login/'>
md2的process_request方法 <wsgirequest: get '/login/'>
<function login at 0x0000002b48eda2f0>
md1的process_view
<function login at 0x0000002b48eda2f0>
md2的process_view
这是login函数
md2的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">
md1的process_response方法 <httpresponse status_code=200, "text/html; charset=utf-8">

执行顺序图

中间件

process_exception

这个比较特殊,只有在有报错的情况下才执行,否则不执行

middleware.py

class md1(middlewaremixin):
    def process_request(self,request):
        #request是一个请求的对象
        print("md1的process_request方法",request)
        # return httpresponse("ok")

    def process_response(self,request,response):
        print("md1的process_response方法",response)
        return response
        # return httpresponse("ok")

    def process_view(self,request,view_func,view_args,view_kwargs):
        print(view_func)
        print("md1的process_view")

    def process_exception(self, request, exception):
        print(exception)
        print("md1的process_exception")

class md2(middlewaremixin):
    def process_request(self,request):
        print("md2的process_request方法",request)
        # return httpresponse("ok")

    def process_response(self,request,response):
        print("md2的process_response方法",response)
        #response 接收的是函数的返回值,是一个response对象
        return response
        # return httpresponse("ok")

    def process_view(self,request,view_func,view_args,view_kwargs):
        print(view_func)
        print("md2的process_view")

    def process_exception(self, request, exception):
        print(exception)    #打印的是抛出的错误信息
        print("md2的process_exception")

为了报错修改views.py代码

def home(request):
    print("这是home函数")
    return render(request,"home.html")

def login(request):
    if request.method == "get":
        print("这是login函数")
        raise valueerror("抛出错误")   #------注意此处要抛错才能执行exception
        return render(request,"login.html")
    else:
        user = request.post.get("username")
        pwd = request.post.get("password")
        if user == "alex" and pwd == "123":
            request.session["is_login"] = true
            return redirect("home")
        else:
            return redirect("login")

def index(request):
    print("这是index函数")
    return render(request,"index.html")

执行结果

md1的process_request方法 <wsgirequest: get '/login/'>
md2的process_request方法 <wsgirequest: get '/login/'>
<function login at 0x0000000ad8f5a268>
md1的process_view
<function login at 0x0000000ad8f5a268>
md2的process_view
这是login函数
抛出错误
md2的process_exception
抛出错误
md1的process_exception
internal server error: /login/
traceback (most recent call last):
  file "c:\python36\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
    response = get_response(request)
  file "c:\python36\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  file "c:\python36\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  file "d:\django项目\day67\zhongjianjian\app01\views.py", line 23, in login
    raise valueerror("抛出错误")
valueerror: 抛出错误
[16/oct/2019 17:25:55] "get /login/ http/1.1" 500 65127
md2的process_response方法 <httpresponse status_code=500, "text/html">
md1的process_response方法 <httpresponse status_code=500, "text/html">

中间件