zoukankan      html  css  js  c++  java
  • python 终极篇 ---- 中间件

    中间件------------------------>>>>>>>>>>>>>
        中间件是一个用来处理django的响应与请求的框架级别的钩子.它是一个轻量,低级别的插件系统,
        用于在全局范围内改变django的输入和输出,每个中间件组件都负责做一些特定的功能.
        
        ----简单来说,Django的中间件是一个类。用来在全局范围内处理请求和响应。
        
        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)
        
        1. process_request
            1. 执行时间
                在视图函数之前执行
            2. 参数
                request 和视图中的request是同一个
            3. 返回值
                返回None  
                返回response对象   
                    不执行后面中间的process_request方法和视图
                    直接执行当前值中间件的process_response方法
            4. 执行顺序
                按照注册的顺序执行 
                
                
        2. process_response    
            1. 执行时间    
                在视图函数之后执行
            2. request, response
                request 和视图中的request是同一个
                response 返回的response对象
            3. 返回值
                返回response对象
            4. 执行顺序
                按照注册的倒序执行
        
        
        3. process_view
            1. 执行时间
                在视图函数之前,process_request之后执行
            2. 参数
                view_func  将要执行的视图函数
                view_args  视图函数的可变长位置参数
                view_kwargs    视图函数的可变长关键字参数
            3. 返回值
                返回  None  正常执行 
                返回  response对象   不执行后面的process_view和视图,直接执行所有中间件的process_response方法
                
            4。执行顺序
                按照注册的顺序执行
        
        4. process_exception(有条件触发:有错误才执行)
                    1. 执行时间
                        在视图函数之后,process_response之前执行
                    2. 参数
                        exception  错误对象
                    3. 返回值
                        返回  None  不对错误进行处理,交给下一个中间件进行处理
                        返回  response对象  下一个中间的process_exception不执行,直接执行所有中间件的process_response方法
                    4. 执行顺序
                        按照注册的倒序执行
        5. process_template_response(条件触发:视图返回的response有render方法)
            1. 执行时间
                在视图函数之后,process_response之前执行
            2. 参数
            3. 返回值
                返回 response对象
            4. 执行顺序
                按照注册的倒序执行,执行完所有的process_template_response方法后执行response.render方法
        

                            中间件的执行流程                           

    上一部分,我们了解了中间件中的5个方法,它们的参数、返回值以及什么时候执行,现在总结一下中间件的执行流程。

    请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法,将HttpResponse对象返回给浏览器。也就是说:如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。

     

    process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。假如中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。

    process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

     

     小练习:

    (1)

    AuthMD中间件注册后,所有的请求都要走AuthMD的process_request方法。

    如果URL在黑名单中,则返回This is an illegal URL的字符串;

    访问的URL在白名单内或者session中有user用户名,则不做阻拦走正常流程;

    正常的URL但是需要登录后访问,让浏览器跳转到登录页面。

    注:AuthMD中间件中需要session,所以AuthMD注册的位置要在session中间的下方。 

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/',views.login),
        url(r'^home/',views.home),
        url(r'^index/',views.index),
        url(r'^logout/',views.logout),
    ]
    urls
    from django.shortcuts import render,HttpResponse,redirect
    from django.conf import global_settings
    # Create your views here.
    
    def login(request):
        err_msg = ""
        if request.method == "POST":
            name = request.POST.get("name")
            pwd = request.POST.get("pwd")
            if name == "alex" and pwd == "123":
                request.session['user'] = "user"
                # request.session.set_expiry(0)   #设置关闭浏览器后自动注销
                return_path = request.GET.get("return","")
                if return_path:
                    return redirect(return_path)
                else:
                    return redirect("/home/")
    
            else:
                err_msg = "用户名或者密码错误"
        return render(request,"login.html",{"err_msg":err_msg})
    
    
    # 登陆装饰器
    # def wrap(func):
    #     def inner(request,*args,**kwargs):
    #         if request.session.get("is_login","") == "True":
    #             ret = func(request,*args,**kwargs)
    #             return ret
    #         else:
    #             path = request.path_info
    #             return redirect("/login/?return={}".format(path))
    #     return inner
    
    
    # @wrap
    def home(request):
        return render(request,"home.html")
    
    
    # @wrap
    def index(request):
        return render(request,"index.html")
    
    
    
    def logout(request):
        del request.session['user']
        return redirect("/login/")
    Views文件
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse, redirect, render
    
    
    class Login_middle(MiddlewareMixin):
        white_list = ["/login/", ]
        black_list = ["/black/", ]
    
        def process_request(self, request):
            path = request.path_info
            if path in self.black_list:
                return HttpResponse("这是黑名单的网址")
            elif path in self.white_list or request.session.get("user"):
                print(11)
                return
            else:
                print(22)
                return redirect("/login/?return={}".format(path))
    中间件
    'app01.my_middlewaremixin.Login_middle'
    settings注册中间件
    #login.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:<input type="text" name="name"></p>
        <p>密码:<input type="password" name="pwd"></p>
        <p><button>提交</button></p><span>{{ err_msg }}</span>
    </form>
    </body>
    </html>
    
    
    #index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎登陆index页面</h1>
    </body>
    </html>
    
    
    
    #home.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎登陆home页面</h1>
    <a href="/logout/">注销</a>
    </body>
    </html>
    template文件 (三个)

    (2) 限制访问频率,一分钟只能访问3次.
        思路:根据IP做判断,1分钟只能访问3次
              1. 获取ip
              2. 记录时间
              3. 根据访问记录做判断
     

    import time
    
    l = {}
    class Throttle(MiddlewareMixin):
        def process_request(self, request):
    
            ip = request.META.get("REMOTE_ADDR")
            now = time.time()
            if not l.get(ip, ""):
                l[ip] = []
            history = l[ip]
            x = []
            for i in history:
                if now - i < 5:
                    x.append(i)
                    print(x)
            history = x
            print(history)
            if len(history) >= 3:
                return HttpResponse("次数太多了")
            history.insert(0, now)
            l[ip] = history
    中间件代码
    request.META 可以获取到所有内容,可以从中找你想用的东西.一组组键值对儿
    # {'ALLUSERSPROFILE': 'C:\ProgramData',
    #  'APPDATA': 'C:\Users\zhanghutao\AppData\Roaming',
    #  'COMMONPROGRAMFILES': 'C:\Program Files\Common Files',
    #  'COMMONPROGRAMFILES(X86)': 'C:\Program Files (x86)\Common Files',
    #  'COMMONPROGRAMW6432': 'C:\Program Files\Common Files',
    #  'COMPUTERNAME': 'DESKTOP-30PDHUE',
    #  'COMSPEC': 'C:\WINDOWS\system32\cmd.exe',
    #  'DJANGO_SETTINGS_MODULE': '中间件.settings',
    #  'HOMEDRIVE': 'C:', 'HOMEPATH': '\Users\zhanghutao',
    #  'LOCALAPPDATA': 'C:\Users\zhanghutao\AppData\Local',
    #  'LOGONSERVER': '\\DESKTOP-30PDHUE',
    #  'MOZ_PLUGIN_PATH': 'E:\Foxit Reader\plugins\',
    #  'NUMBER_OF_PROCESSORS': '4',
    #  'ONEDRIVE': 'C:\Users\zhanghutao\OneDrive',
    #  'OS': 'Windows_NT',
    #  'PATH': 'C:\WINDOWS\system32;'
    # 'C:\WINDOWS;'
    # 'C:\WINDOWS\System32\Wbem;'
    #  'C:\WINDOWS\System32\WindowsPowerShell\v1.0\;'
    #          'C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\WIDCOMM\Bluetooth Software\syswow64;D:\mysql\mysql-5.7.23-winx64\bin;;D:\PPB\PBB Reader\x64;D:\python3.6\Scripts\;D:\python3.6\;C:\Users\zhanghutao\AppData\Local\Microsoft\WindowsApps;;D:\python3.6\lib\site-packages\pywin32_system32;D:\python3.6\lib\site-packages\pywin32_system32', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 58 Stepping 9, GenuineIntel', 'PROCESSOR_LEVEL': '6', 'PROCESSOR_REVISION': '3a09', 'PROGRAMDATA': 'C:\ProgramData', 'PROGRAMFILES': 'C:\Program Files', 'PROGRAMFILES(X86)': 'C:\Program Files (x86)', 'PROGRAMW6432': 'C:\Program Files', 'PSMODULEPATH': 'C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules;C:\Program Files\Intel\Wired Networking\', 'PUBLIC': 'C:\Users\Public', 'PYCHARM_HOSTED': '1', 'PYCHARM_MATPLOTLIB_PORT': '54693', 'PYTHONIOENCODING': 'UTF-8', 'PYTHONPATH': 'D:\pycharm\PyCharm 2018.1.3\helpers\pycharm_matplotlib_backend;D:\PythonTest\django项目\中间件', 'PYTHONUNBUFFERED': '1', 'SESSIONNAME': 'Console', 'SYSTEMDRIVE': 'C:', 'SYSTEMROOT': 'C:\WINDOWS', 'TEMP': 'C:\Users\ZHANGH~1\AppData\Local\Temp', 'TMP': 'C:\Users\ZHANGH~1\AppData\Local\Temp', 'USERDOMAIN': 'DESKTOP-30PDHUE', 'USERDOMAIN_ROAMINGPROFILE': 'DESKTOP-30PDHUE', 'USERNAME': 'zhanghutao', 'USERPROFILE': 'C:\Users\zhanghutao', 'WINDIR': 'C:\WINDOWS', 'RUN_MAIN': 'true', 'SERVER_NAME': 'DESKTOP-30PDHUE', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/index/', 'QUERY_STRING': '',
    #  'REMOTE_ADDR': '127.0.0.1',
    #  'CONTENT_TYPE': 'text/plain',
    #  'HTTP_HOST': '127.0.0.1:8000',
    #  'HTTP_CONNECTION': 'keep-alive', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_COOKIE': 'csrftoken=HSERiDbpYwWLfLhrjDIgcsMP8HjD1CqXuSPjgSD40l8YpqbMPTYaNKl3xm6MLWne; sessionid=qfrad5a76h2ozt0erj74wef1nrzsl63n', 'wsgi.input': <_io.BufferedReader name=964>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>, 'CSRF_COOKIE': 'HSERiDbpYwWLfLhrjDIgcsMP8HjD1CqXuSPjgSD40l8YpqbMPTYaNKl3xm6MLWne'}
    例如:
  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/dalaoban/p/9699675.html
Copyright © 2011-2022 走看看