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

 更新时间:2018年02月06日 10:34:56   作者:扎心了老铁  
这篇文章主要介绍了Django中间件工作流程及写法实例代码,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

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

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

1、Middleware的工作流程

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

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

总结

以上就是本文关于Django中间件工作流程及写法实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

相关文章

  • Python tkinter模块弹出窗口及传值回到主窗口操作详解

    Python tkinter模块弹出窗口及传值回到主窗口操作详解

    这篇文章主要介绍了Python tkinter模块弹出窗口及传值回到主窗口操作,结合实例形式分析了Python使用tkinter模块实现的弹出窗口及参数传递相关操作技巧,需要的朋友可以参考下
    2017-07-07
  • Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程

    Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程

    Flask-Migrate可以帮助Flask应用程序通过预设的Python脚本完成数据库迁移操作,这里我们就来看一下Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程,需要的朋友可以参考下
    2016-06-06
  • 浅谈python爬虫使用Selenium模拟浏览器行为

    浅谈python爬虫使用Selenium模拟浏览器行为

    这篇文章主要介绍了浅谈python爬虫使用Selenium模拟浏览器行为,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • python 基于opencv实现高斯平滑

    python 基于opencv实现高斯平滑

    这篇文章主要介绍了python 基于opencv实现高斯平滑,帮助大家更好的理解和使用python处理图片,感兴趣的朋友可以了解下
    2020-12-12
  • 浅谈对python中if、elif、else的误解

    浅谈对python中if、elif、else的误解

    这篇文章主要介绍了浅谈对python中if、elif、else的误解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Python函数式编程中itertools模块详解

    Python函数式编程中itertools模块详解

    这篇文章主要介绍了在Python中使用itertools模块中的组合函数的教程,来自IBM官方技术文档,需要的朋友可以参考下,希望能够给你带来帮助
    2021-09-09
  • Python卸载模块的方法汇总

    Python卸载模块的方法汇总

    本文给大家汇总介绍了3种卸载Python已安装模块的方法,推荐大家使用easy_install或者pip的方式来进行,简单方便
    2016-06-06
  • Python使用jupyter notebook查看ipynb文件过程解析

    Python使用jupyter notebook查看ipynb文件过程解析

    这篇文章主要介绍了Python使用jupyter notebook查看ipynb文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • pd.DataFrame中的几种索引变换的实现

    pd.DataFrame中的几种索引变换的实现

    本文主要介绍了pd.DataFrame中的几种索引变换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Jacobi迭代算法的Python实现详解

    Jacobi迭代算法的Python实现详解

    这篇文章主要介绍了Jacobi迭代算法的Python实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-06-06

最新评论