zoukankan      html  css  js  c++  java
  • django框架进阶中间件长期维护

    ##################    为什么使用中间件?      #######################

    先说几个需求,
    1,url的白名单,url=[ "XX"],这个里面是一个用户可以访问的url,这就是一个权限的概念了,  
    2,登陆之后才能访问某些url,之前使用的是装饰器,一个网站可能有一两千的url,这样加装饰器就不太好,所以使用中间件是非常不错的,

    ##################    什么是中间件?      #######################

    什么是中间件以及中间件的作用?
    是一个轻量,低级别的插件系统,可以在全局范围内改变django的输入和输出,每一个中间件都负责做一些特定的功能。
    也就是每一个请求都会走这个中间件,
    
    注意:
    因为改变的是全局,所以要谨慎使用,使用不当会影响性能,
    
    
    浏览器到django框架的时候,
    1,先经过一个wsgi,这个wsgi就是按照HTTP的协议的规则解析请求,
    2,然后到中间件,
    3,然后到url.py中,找对应关系
    4,然后去views.py中,找到对应的函数,这个函数需要模板,需要数据,
    5,然后可能去读一个模板templates,html页面,使用orm取数据,
    django把数据渲染之后返回到浏览器,经过视图函数,经过url,经过wsgi,这个还需要按照HTTP的协议,进行解析,然后输出,
    中间件就是经过wsgi之后就要经过中间件,这就是在全局影响django的请求和响应,
    
    所以中间件,在wsgi之后,在url.py之前,在全局,操作django请求和响应的模块,
    
    所以中间件多了不好,每次都经过,性能就会受到影响,
    所以前面权限的例子,就是可以使用中间件的,这好像是一个过滤的功能一样,
    比如验证是否登陆,如果没有登陆就提示登陆,登陆了就可以查看,这个也可以使用中间件
    所以全网站级别的功能,就需要使用中间件,
    
    这个是一个比较进阶的东西,你不知道不影响你写什么东西,

    ##################    自定义中间件      #######################

    中间件可以定义五个方法,分别是:(主要的是process_request和process_response)
    
    process_request(self,request)
    这个方法的执行顺序是按照在setting里面的设置,从上往下执行
    
    process_view(self, request, view_func, view_args, view_kwargs)
    执行顺序也是从上到下
    什么时候执行的,这个比较特殊,是在url.py找到了对应的视图函数之后,在真正的视图函数执行之前,执行的,
    
    process_template_response(self,request,response)
    这个方法的执行顺序是按照在setting里面的设置,从下往上执行
    在视图函数执行完,在执行视图函数返回的render之前执行,
    
    process_exception(self, request, exception)
    这个方法的执行顺序是按照在setting里面的设置,从下往上执行
    是在自己写的视图函数抛出异常的时候,执行这个异常函数
    
    process_response(self, request, response)
    这个方法的执行顺序是按照在setting里面的设置,从下往上执行
    
    以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。
    
    ####################################
    
    这五个方法也是有执行顺序的
    1,process_request
        url.py
    2,process_view
        view.py
    3,有异常就执行,process_exception
    4,如果视图返回的响应对象中render方法,就执行process_template_response
    5,process_response
    只需要掌握process_request和process_response,其他的了解,
    
    注意,
    1,如果有6个中间件,执行顺序是先全部执行request,然后全部执行view,然后倒序全部执行response
    2,如果第三个中间件的process_request有返回值,后面的中间件就断了,直接是执行1,2,3的view和3,2,1的response,剩下的456就不管了 
    3,但是如果第三个的process_view有返回值了,执行的是1,2,34,5,6的request,然后是1,2,3的view,但是是执行的6,5,4,3,2,1,的response,

    ##################    中间件自定义代码      #######################

    from django.shortcuts import HttpResponse, redirect
    
    """
    自定义的中间件
    """
    from django.utils.deprecation import MiddlewareMixin
    
    # 定义一个可以访问的白名单
    URL = ["/oo/", "/xx/", "/haha/"]
    
    class OoXx(MiddlewareMixin):
    
        # def process_request(self, request):
        #     print("这是我的第一个中间件:OoXx!")
        #     print(id(request))
        #     # print(request.path_info)  # 获取访问的url的路径,
        #     # # 如果用户访问的URL 在 白名单里面
        #     # if request.path_info in URL:
        #     #     return  # 这是返回None,
        #     # # 否则 直接返回一个 响应 不走视图那部分了
        #     # else:
        #     #     return HttpResponse("gun!")
        #
        # def process_response(self, request, response):
        #     """
        #     :param request: 是浏览器发来的请求对象
        #     :param response: 是视图函数返回的响应对象
        #     :return:
        #     """
        #     print("这是OOXX中间件里面的 process_response")
        #     # return response
        #     return HttpResponse("hahahaha")
        #
        # def process_view(self, request, view_func, view_args, view_kwargs):
        #     """
        #
        #     :param request: 浏览器发来的请求对象
        #     :param view_func: 将要执行的视图函数的名字
        #     :param view_args: 将要执行的视图函数的位置参数
        #     :param view_kwargs: 将要执行的视图函数的关键字参数
        #     :return:
        #     """
        #     print("ooxx里面的process_view")
        #     print(view_func, type(view_func))
        #     return HttpResponse("ooxx:process_view")
    
    
        # def process_exception(self, request, exception):
        #     print(exception)
        #     print("ooxx里面的process_exception")
        #     return redirect("http://www.luffycity.com")
    
        # def process_template_response(self, request, response):
        #     print("ooxx 中的process_template_response")
        #     return response
    
        def process_request(self, request):
           request.s10 = {"is_login": 1, "name": "s10"}
    
    
    
    class MD2(MiddlewareMixin):
    
        # def process_request(self, request):
        #     print("这是我的第二个中间件:MD2!")
        #     print(id(request))
        #
        # def process_response(self, request, response):
        #     print("这是MD2中间件里面的 process_response")
        #     return response
        #
        # def process_view(self, request, view_func, view_args, view_kwargs):
        #     print("MD2里面的process_view")
        #     print(view_func, type(view_func))
        #     return HttpResponse("md2:process_view")
    
        # def process_exception(self, request, exception):
        #     print(exception)
        #     print("MD2里面的process_exception")
    
        # def process_template_response(self, request, response):
        #     print("MD2 中的process_template_response")
        #     return response
    
    
        def process_request(self, request):
           print(request.s10.get("is_login"))

    ##################    中间件版登录验证      #######################

    中间件版的登录验证需要依靠session,所以数据库中要有django_session表。

    urls.py

    from django.conf.urls import url
    from app01 import views
    
    urlpatterns = [
        url(r'^index/$', views.index),
        url(r'^login/$', views.login, name='login'),
    ]
    
    urls.py

    view.py

    from django.shortcuts import render, HttpResponse, redirect
    
    
    def index(request):
        return HttpResponse('this is index')
    
    
    def home(request):
        return HttpResponse('this is home')
    
    
    def login(request):
        if request.method == "POST":
            user = request.POST.get("user")
            pwd = request.POST.get("pwd")
    
            if user == "andy" and pwd == "123456":
                # 设置session
                request.session["user"] = user
                # 获取跳到登陆页面之前的URL
                next_url = request.GET.get("next")
                # 如果有,就跳转回登陆之前的URL
                if next_url:
                    return redirect(next_url)
                # 否则默认跳转到index页面
                else:
                    return redirect("/index/")
        return render(request, "login.html")
    
    views.py

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>登录页面</title>
    </head>
    <body>
    <form action="{% url 'login' %}">
        <p>
            <label for="user">用户名:</label>
            <input type="text" name="user" id="user">
        </p>
        <p>
            <label for="pwd">密 码:</label>
            <input type="text" name="pwd" id="pwd">
        </p>
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    
    login.html

    middlewares.py:

    class AuthMD(MiddlewareMixin):
        white_list = ['/login/', ]  # 白名单
        balck_list = ['/black/', ]  # 黑名单
    
        def process_request(self, request):
            from django.shortcuts import redirect, HttpResponse
    
            next_url = request.path_info
            print(request.path_info, request.get_full_path())
    
            if next_url in self.white_list or request.session.get("user"):
                return
            elif next_url in self.balck_list:
                return HttpResponse('This is an illegal URL')
            else:
                return redirect("/login/?next={}".format(next_url))
    

    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',
        'middlewares.AuthMD',
    ]

    ################################################

    ################################################

    ################################################

    ################################################

  • 相关阅读:
    Subsets
    Reverse Linked List II
    【转】MySQL— 进阶
    【转】MySQL— 基础
    【转】Python-面向对象进阶
    【转】python f-string
    【转】Python基础-封装与扩展、静态方法和类方法
    【转】HTML
    【转】HTTP
    【转】Python3 configparse模块(配置)
  • 原文地址:https://www.cnblogs.com/andy0816/p/12191281.html
Copyright © 2011-2022 走看看