zoukankan      html  css  js  c++  java
  • 07.Django-中间件

    中间件

    django的生命周期是: 前端请求 ---> nginx ---> uwsgi ---> 中间件 ---> url路由 ----> view试图 --> orm ----> 拿到数据返回给view ----> 试图将数据渲染到模版中拿到字符串 ---> 中间件- ---> uwsgi ---> nginx ----> 前端渲染。

    当一个请求,首先从上往下运行这些类中process_request方法,之后进入django的从上往下执行每个类中的process_view方法,在然后就进入我们自定义的view.py文件,如果你的试图中有错误,那就会从下往上执行中间件中的process_exception方法,然后把错误信息在通过process_response中返回给客户端。

    一、简介

    1. Django的中间件类似于Linux中的管道符;
    2. Django的中间件实质就是一个雷,类之中有Django已经定义好了一些方法;
    3. Django内部的中间件注册在setting,py文件;
    4. 对全局的http请求做处理的时候可以使用中间件;
    5. 中间件中的方法不一定要全部使用,需要哪个用哪个;
    6. Django的中间件继承自MiddlewareMixin这个中间件
    7. MiddlewareMixin是调用了其内部的__call__方法,__call__方法以反射的方式执行process_request和process_response方法。

    二、中间件方法

    • process_request(self,request)

      process_request有一个参数,就是request,这个request和视图函数中的request是一样的。

      它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。

      在这个方法中是没有return方法的,如果有那就会执行process_response方法,直接返回给客户端,一般情况下我们是不会在这里返回内容的,除非你有需求,判断发过来的请求过来的内容,如果不是很友好的请求,那么我们直接就可以在这返回,直接卡死,让这个请求直接都进不了我们的django中的内部程序

    • process_response(self, request, response)

      它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象。

      在这个方法中我们必须要有return方法,这样才能一步一步的返回给客户端,当然你也可以写一些东西在response里,在这里写就是会在所有的response里都会有你所添加的内容!

    • process_view(self, request, view_func, view_args, view_kwargs)

      该方法有四个参数
      request是HttpRequest对象。
      view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
      view_args是将传递给视图的位置参数的列表.
      view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。

      Django会在调用视图函数之前调用process_view方法。

      它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。

      先执行路由匹配,再执行process_view方法,再执行视图函数
      这个方法中是没有return方法的,如果有那就走process_response方法,视图函数不会执行

    • process_exception(self, request, exception)

      该方法两个参数:
      一个HttpRequest对象
      一个exception是视图函数异常产生的Exception对象。

      这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

    • process_template_response(self,request,response)

      它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。

      process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。

    三、中间件的应用

    基于中间件实现简单用户登录验证

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

    定义路由

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

    视图函数

    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 == "Q1mi" 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")
    

    定义页面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>
    

    定义中间件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))
    

    注册

    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',
    ]
    

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

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

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

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

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

    四、附:Django请求流程图

  • 相关阅读:
    31 整数中1出现的次数(从1到n整数中1出现的次数)
    算法寒假实习面试经过之 十一贝(offer) 联想研究院(电话一面 被拒)
    百度feed 寒假实习 一面二面(offer)
    30连续子数组的最大和
    29最小的K个数
    28数组中出现次数超过一半的数字
    MySQL操作数据库和表的基本语句(DDL)
    Oracle————存储过程与函数
    Oracle清空数据库中数据表数据的方法
    Linux之常用Shell脚本总结
  • 原文地址:https://www.cnblogs.com/yanadoude/p/13093491.html
Copyright © 2011-2022 走看看