Django之中间件

1、django 的请求生命周期

  说明:

    1. wsgiref是django自带的模块,但由于效率低,一般使用的是uwsgi模块,同时使用nignx做负载均衡。

    2. WSGI、uwsgi和wsgiref之间的区别:WSGI是一个协议,uwsgi、wsgiref和werkzeug 都是django基于WSGI开发的一个模块

2、中间件

  官方解释:中间件是一个用来处理django的请求和响应的框架级别的钩子,它是一个轻量、低级别的插件系统,用于在全局范围内改变django的输入输出。每个中间件组件都负责特定的功能

  2.1 django 中间件

    默认7个中间件,在settings.py文件下的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',
]

    执行顺序:请求来后,按照上面的顺序从上到下一个一个执行中间件,返回时,从下到上

  2.2 中间件中方法

    django 中间件可以定义的方法有5个:

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)

# 说明:以上方法都可返回None和HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。

    1. process_request

      语法:process_request(self, request)

      参数:request和视图函数的request是一样的。在交给Django后面的路由之前,对这个request对象可以进行一系列的操作。

      执行时间:请求到达每个中间件时,第一个执行process_request.

    2. process_response

      语法:process_response(self, request, response)

      参数:

        request和视图函数的request是一样的。

        response是视图函数返回的HttpResponse对象。该方法必须要有返回值,也必须是HttpResponse对象。如果不返回response而返回其他对象,则浏览器不能正常显示html文件

      执行时间:经过view.py返回数据时,从下到上,到达每个中间件,执行该方法

    3. process_view

      语法:process_view(self, request,view_func,view_args,view_kwargs)

      参数:

         request是HttpRequest对象。

        view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)

        view_args是将传递给视图的位置参数的列表.

         view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)

      执行时间:从上到下执行完每个中间件的process_request后,执行urls.py路由分发,再调头,还是从上到下执行每个中间件的process_view方法。

    4. process_exception

      语法:process_exception(self, request, exception)

      参数:

        request是HttpRequest对象

        exception是视图函数异常产生的Exception对象。

      执行时间:只有在视图函数出现异常时执行,从下到上执行每个中间件的该方法。

    5. process_template__response

      语法:process_template_response(self, request, response)

      参数:

        request和视图函数的request是一样的。

        response是视图函数返回的HttpResponse对象。该方法必须要有返回值,也必须是HttpResponse对象。

      执行时间:该方法只有在视图函数返回中有自定义的render方法时才执行。从下到上执行每个中间件的process_template_response方法。

class MyRender():
    def __init__(self, request, msg):
        self.request = request
        self.msg = msg

    def render(self):
        return HttpResponse(self.msg)

def index(request):
    print(" This is index...")
    return MyRender(request,"This is index...")

  2.3 中间件执行过程

     说明:

      1. 中间件M1、M2、M3的顺序MIDDLEWARE = ['M1', "M2", "M3"]

      2. 红色1,2,3分别代表:如果该函数有返回值一个HttpResponse对象时,走的(”捷径“)路线

      3. exception和template_response 不会同时执行

   2.4 自定义中间件

    1、在项目下创建文件夹mymiddleware,名字任意

    2、添加py文件,my_middleware.py

    3. 导入父类,from django.utils.deprecation import MiddlewareMixin

    4. 在文件中添加中间件

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class M1(MiddlewareMixin):
    def process_request(self, request):
        print("M1的 reuqest")

    def process_response(self, request, response):
        print("M1 的response")
        return response

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

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

    def process_template_response(self, request, response):
        print("M1 的 template_response")
        return response

    5. 在settings.py 的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',
    "mymiddleware.my_middleware.M1",
]

3、示例:使用中间件做登陆验证

def login(request):
    """中间件对用户登录验证"""
    if request.method == "GET":
        return render(request, "login.html")
    else:
        name = request.POST.get("name")
        pwd = request.POST.get("pwd")
        if name == "sun" and pwd == "123":
            request.session["login"] = "OK"
            return_url = request.GET.get("returnURL")
            print(request.GET)
            return redirect(return_url or "/home/")
        else:
            return HttpResponse("用户名或密码错误")


def index(request):
    """只有登录后才能查看"""
    return HttpResponse("This is index....")


def home(request):
    """只有登录后才能查看"""
    return HttpResponse("This is home....")
views.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect

class LoginAuth(MiddlewareMixin):

    def process_request(self, request):
        return_url = request.path #type:str
        if not return_url.startswith("/login"):
            if not request.session.get("login", ""):
                return redirect("/login/?returnURL=%s"%return_url)
中间件
<!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
      <link rel="stylesheet" href="/static/bootstrap3/css/bootstrap.min.css" />
      <script src="/static/bootstrap3/js/bootstrap.min.js"></script>
    </head>
  <body>
    <div class="container">
      <div class="row col-sm-8 col-sm-offset-2">
        <form class="form-horizontal" method="post" action="">
          <div class="form-group">
            <label for="inputname" class="col-sm-2 control-label">
              用户名
            </label>
            <div class="col-sm-9">
              <input type="text" class="form-control" id="inputname" placeholder="用户姓名" name="name">
            </div>
          </div>
          <div class="form-group">
            <label for="inputpwd" class="col-sm-2 control-label">
              密码
            </label>
            <div class="col-sm-9">
              <input type="text" class="form-control" id="inputpwd" placeholder="用户密码" name="pwd">
            </div>
          </div>
          <div class="form-group">
            <div class="col-sm-offset-2 col-sm-9">
              <button type="submit" class="btn btn-primary">登录</button>
            </div>
          </div>
        </form>
      </div>
    </div>
  </body>
</html>
login.html 直接复制

 

 
posted @ 2019-04-30 13:09  yw_sun  阅读(167)  评论(0)    收藏  举报