Django中间件工作流程及写法实例代码

作者:扎心了老铁 时间:2021-09-01 17:47:38 

熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截。

django中的中间件(middleware)就是类似钩子的一种存在。下面我们来介绍一下,并且给出一些实例。

1、Middleware的工作流程

Django中间件工作流程及写法实例代码

我盗了一个图,看网上很多人用这个图,来源已经追不明白了。简单声明一下,这个图不是我的。看着图我们分析一下:

1)django的请求相应流程:HttpRequest -> RequestMiddleware -> view function -> ResponseMiddleware -> HttpResponse

可以看到一个请求到响应的过程,中间夹着两个middleware流程,请求中间件和响应中间件。

也就是说,django提供了一种机制,在:

  1. 请求到达视图函数中间

  2. 视图函数到响应之间

支持嵌入钩子。

这种钩子的特点:

  1. 全局,一旦你使用了中间件,并且发布生效的话,所有的请求都会经过你嵌入的中间件。

  2. 性能敏感,如果你的中间件性能差的话,那么会影响服务的整体性能。

2) django的middleware包含四个钩子函数:process_request/process_view/process_response/process_exception

process_request:接受request之后确定所执行的view之前

process_view:确定了所要执行的view之后,view真正执行之前

process_response:view执行之后

process_exceptionview:view执行抛出异常

而插入middleware的过程是在settings.py中配置,如下默认配置,我只截取了两个中间件:SessionMiddleware和CommonMiddleware。


MIDDLEWARE_CLASSES = (
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',

...    
)

我们简单看一下SessionMiddleware的实现


import time
from importlib import import_module

from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date

class SessionMiddleware(object):
 def __init__(self):
   engine = import_module(settings.SESSION_ENGINE)
   self.SessionStore = engine.SessionStore

def process_request(self, request):
   session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
   request.session = self.SessionStore(session_key)

def process_response(self, request, response):
   """
   If request.session was modified, or if the configuration is to save the
   session every time, save the changes and set a session cookie or delete
   the session cookie if the session has been emptied.
   """
   try:
     accessed = request.session.accessed
     modified = request.session.modified
     empty = request.session.is_empty()
   except AttributeError:
     pass
   else:
     # First check if we need to delete this cookie.
     # The session should be deleted only if the session is entirely empty
     if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
       response.delete_cookie(settings.SESSION_COOKIE_NAME)
     else:
       if accessed:
         patch_vary_headers(response, ('Cookie',))
       if modified or settings.SESSION_SAVE_EVERY_REQUEST:
         if request.session.get_expire_at_browser_close():
           max_age = None
           expires = None
         else:
           max_age = request.session.get_expiry_age()
           expires_time = time.time() + max_age
           expires = cookie_date(expires_time)
         # Save the session data and refresh the client cookie.
         # Skip session save for 500 responses, refs #3881.
         if response.status_code != 500:
           request.session.save()
           response.set_cookie(settings.SESSION_COOKIE_NAME,
               request.session.session_key, max_age=max_age,
               expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
               path=settings.SESSION_COOKIE_PATH,
               secure=settings.SESSION_COOKIE_SECURE or None,
               httponly=settings.SESSION_COOKIE_HTTPONLY or None)
   return response

可以看到在SessionMiddleware中默认只实现了process_requestprocess_response两个hook函数。

我们就以这个例子说明一下一个请求的执行过程。我们假设场景是这样的:

1)从上而下配置了两个Middleware(注意顺序):SessionMiddleware和CommonMiddleware

2)每个Middleware中的四个钩子函数齐全process_request/process_view/process_response/process_exception

执行顺序应该是这样的:

1、HttpRequest

2、SessionMiddleware process_request

3、SessionMiddleware process_view

4、CommonMiddleware process_request

5、CommonMiddleware process_view

6、view

7、CommonMiddleware process_response

8、CommonMiddleware process_exception(如有必要)

9、SessionMiddleware process_response

10、SessionMiddleware process_exception(如有必要)

11、HttpResponse

2、Middleware的写法

Middleware的写法很简单:

1)实现一个类,继承object就行;

2)重写其中的四个钩子函数就可以了。

这里要着重说一个常用的功能。

* /过滤器(filter)

一般来说,每一个请求都要经过process_request这个钩子函数。你的实现中,函数的执行结果必然有两种(你要自己做异常处理):

1)None

2)HttpResponse 对象

如果返回None,请求流程继续执行,也就是继续进入其他的Middleware或者钩子函数。

如果返回HttpResponse对象,那么就直接返回到页面。通过这个功能我们可以做黑名单。

给一个例子:

就是统计pv


# -*- coding:utf-8 -*-
from datetime import datetime
from data_monitor.utils.dbmanager import MysqlManager
from data_monitor.common.constant import MYSQL_JOBS as mysql_config

class RequestHookMiddleware(object):

def process_request(self, request):
   try:
     username = request.COOKIES.get('username')
     uri = request.path
     timestamp = str(datetime.now())
     db_obj = MysqlManager(
       mysql_config.get('host'),
       mysql_config.get('port'),
       mysql_config.get('db'),
       mysql_config.get('user'),
       mysql_config.get('password'),
       format=True,
     )
     field_str = 'username, uri, timestamp'
     value_str = '"%s","%s","%s"' % (username, uri, timestamp)
     db_obj.insert('pv', field_str, value_str)
     db_obj.close()
     return
   except Exception, ex:
     return

来源:http://www.cnblogs.com/kangoroo/p/7358431.html

标签:python,django,中间件
0
投稿

猜你喜欢

  • 对python csv模块配置分隔符和引用符详解

    2023-04-14 13:52:20
  • python训练数据时打乱训练数据与标签的两种方法小结

    2021-11-17 11:15:12
  • Python基于list的append和pop方法实现堆栈与队列功能示例

    2022-10-20 02:26:26
  • python os.listdir()乱码解决方案

    2021-09-20 02:52:42
  • 基于Numba提高python运行效率过程解析

    2022-09-10 11:00:38
  • 在Pycharm中修改文件默认打开方式的方法

    2023-03-12 06:34:23
  • 苹果的“创新”

    2010-01-12 13:45:00
  • 使用WingPro 7 设置Python路径的方法

    2022-05-23 03:59:56
  • 关于Kotlin中SAM转换的那些事

    2022-02-09 15:14:38
  • Python实现的寻找前5个默尼森数算法示例

    2023-05-15 17:34:29
  • Golang中goroutine和channel使用介绍深入分析

    2023-07-07 16:51:48
  • 网马解密大讲堂——网马解密中级篇(Freshow工具使用方法)

    2009-09-16 15:09:00
  • opencv实现简单人脸识别

    2021-08-26 07:49:06
  • python记录程序运行时间的三种方法

    2023-08-25 03:12:19
  • 细化解析:Mysql数据库对文件操作的封装

    2008-11-27 16:32:00
  • 5个充满想象力的Web调色板

    2008-08-02 12:55:00
  • python列表中常见的一些排序方法

    2023-08-17 08:48:45
  • c++生成dll使用python调用dll的方法

    2023-02-16 11:40:05
  • Python全景系列之数据类型大盘点

    2021-01-10 15:29:19
  • 一个入门级python爬虫教程详解

    2023-03-27 17:34:08
  • asp之家 网络编程 m.aspxhome.com