详解django自定义中间件处理


Posted in Python onNovember 21, 2018

中间件是一个钩子框架,它们可以介入 Django 的请求和响应处理过程。 它是一个轻量级、底层的 插件 系统,用于在 全局修改 Django 的输入或输出 。

每个中间件组件负责完成某个特定的功能

这里介绍的中间件方法适用于 Django1.10 以上

相关文件: django middleware

Django基础中间件

django.utils.deprecation.py

class MiddlewareMixin(object):
 def __init__(self, get_response=None):
  self.get_response = get_response
  super(MiddlewareMixin, self).__init__()

 def __call__(self, request):
  response = None
  if hasattr(self, 'process_request'):
   response = self.process_request(request)
  if not response:
   response = self.get_response(request)
  if hasattr(self, 'process_response'):
   response = self.process_response(request, response)
  return response

以上为Django基础中间件源码,要习惯于看源码,上面的这段代码并不复杂,下面我们来一一解释。

def __init__(self, get_response=None):
 self.get_response = get_response
 super(MiddlewareMixin, self).__init__()

熟悉 python 类的都不陌生 __init__ 方法, 这里主要是 一次性配置和初始化

def __call__(self, request):
  response = None
  if hasattr(self, 'process_request'):
    response = self.process_request(request)
  if not response:
    response = self.get_response(request)
  if hasattr(self, 'process_response'):
    response = self.process_response(request, response)
  return response

__call__ 为每个请求/响应执行的代码

self.process_request(request) 为每个请求到调用视图之前的操作,通常可以在这里做一些用户请求频率的控制。

self.get_response(request) 为调用视图

self.process_response(request, response) 为调用视图完成后的操作

自定义中间件

刚才了解了基础中间件,现在就开始编写我们自己的中间件。

通常我们回去继承基础中间件来实现自己的功能

from django.utils.deprecation import MiddlewareMixin

class PermissionMiddlewareMixin(MiddlewareMixin):
  """
  django 中间件
  """

  def process_request(self, request):
    pass

  def process_response(self, request, response):
    return response

如果你要在请求之前做处理,需要定义 process_request() 方法,去实现相关功能

如果你要在视图调用之后做处理,需要定义 process_response() 方法,去实现相关功能

:warning:注意 定义 process_response() 方法一定要 return response

需要将你编写的中间件添加到 settings 中的 MIDDLEWARE 里

我这里写了一个通过中间件限制客户端请求频率,有兴趣的可以看一下

django中间件客户端请求频率限制

通过redis lua脚本对客户端IP请求频率限制

# coding:utf-8

__author__ = 'carey@akhack.com'

from django.utils.deprecation import MiddlewareMixin
from django.http.response import HttpResponse
from django_redis import get_redis_connection
from hashlib import md5


class RequestBlockMiddlewareMixin(MiddlewareMixin):
  """
  django中间件客户端请求频率限制
  """

  limit = 4 # 单位时间内允许请求次数
  expire = 1 # 限制时间
  cache = "default" # 获取django cache

  def process_request(self, request):
    num = self.set_key(request)
    if num > self.limit:
      return HttpResponse("请求频率过快,请稍后重试", status=503)

  @staticmethod
  def get_ident(request):
    """
    Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
    if present and number of proxies is > 0. If not use all of
    HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
    """
    NUM_PROXIES = 1
    xff = request.META.get('HTTP_X_FORWARDED_FOR')
    remote_addr = request.META.get('REMOTE_ADDR')
    num_proxies = NUM_PROXIES

    if num_proxies is not None:
      if num_proxies == 0 or xff is None:
        return remote_addr
      addrs = xff.split(',')
      client_addr = addrs[-min(num_proxies, len(addrs))]
      return client_addr.strip()

    return ''.join(xff.split()) if xff else remote_addr

  def get_md5(self, request):
    """
    获取IP md5值
    :param request:
    :return:
    """
    ip_str = self.get_ident(request)
    ip_md5 = md5()
    ip_md5.update(ip_str.encode("utf-8"))
    return ip_md5.hexdigest()

  def set_key(self, request):
    """
    通过redis lua脚本设置请求请求次数和限制时间
    :param request:
    :return: 限制时间内请求次数
    """
    lua = """
      local current
      current = redis.call("incr",KEYS[1])
      if tonumber(current) == 1 then
        redis.call("expire",KEYS[1],ARGV[1])
      end
      return tonumber(redis.call("get", KEYS[1]))
      """
    key = self.get_md5(request)
    redis_cli = get_redis_connection(self.cache)
    data = redis_cli.eval(lua, 1, key, self.expire, self.limit)
    return data

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python发送邮件接收邮件示例分享
Jan 21 Python
简介Python设计模式中的代理模式与模板方法模式编程
Feb 02 Python
Python中MySQL数据迁移到MongoDB脚本的方法
Apr 28 Python
Python多线程threading和multiprocessing模块实例解析
Jan 29 Python
根据DataFrame某一列的值来选择具体的某一行方法
Jul 03 Python
Python多线程threading模块用法实例分析
May 22 Python
Python操作多维数组输出和矩阵运算示例
Nov 28 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
Jan 09 Python
keras slice layer 层实现方式
Jun 11 Python
Python 在局部变量域中执行代码
Aug 07 Python
自定义Django_rest_framework_jwt登陆错误返回的解决
Oct 18 Python
使用numpngw和matplotlib生成png动画的示例代码
Jan 24 Python
pygame游戏之旅 添加游戏界面按键图形
Nov 20 #Python
pygame游戏之旅 添加游戏介绍
Nov 20 #Python
pygame游戏之旅 计算游戏中躲过的障碍数量
Nov 20 #Python
pygame游戏之旅 添加碰撞效果的方法
Nov 20 #Python
pygame游戏之旅 如何制作游戏障碍
Nov 20 #Python
用Python编写一个简单的CS架构后门的方法
Nov 20 #Python
python pygame实现2048游戏
Nov 20 #Python
You might like
详解WordPress开发中的get_post与get_posts函数使用
2016/01/04 PHP
composer.lock文件的作用
2016/02/03 PHP
一次失败的jQuery优化尝试小结
2011/02/06 Javascript
js修改input的type属性及浏览器兼容问题探讨与解决
2013/01/23 Javascript
javascript垃圾收集机制与内存泄漏详细解析
2013/11/11 Javascript
javascript静态页面传值的三种方法分享
2013/11/12 Javascript
JS的参数传递示例介绍
2014/02/08 Javascript
Node.js本地文件操作之文件拷贝与目录遍历的方法
2016/02/16 Javascript
javascript封装addLoadEvent实现页面同时加载执行多个函数的方法
2016/07/25 Javascript
基于jQuery的select下拉框选择触发事件实例分析
2016/11/18 Javascript
简单实现Vue的observer和watcher
2016/12/21 Javascript
js实现自定义路由
2017/02/04 Javascript
微信小程序使用swiper组件实现层叠轮播图
2018/11/04 Javascript
JavaScript如何实现元素全排列实例代码
2019/05/14 Javascript
微信小程序实现折线图的示例代码
2019/06/07 Javascript
微信小程序实现渐入渐出动画效果
2019/06/13 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
2019/08/20 Javascript
纯异步nodejs文件夹(目录)复制功能
2019/09/03 NodeJs
浅谈Vue3.0新版API之composition-api入坑指南
2020/04/30 Javascript
Javascript原型链及instanceof原理详解
2020/05/25 Javascript
[01:28]2014DOTA2国际邀请赛中国区预选赛四大豪门直升机抵达会场
2014/05/24 DOTA
[20:30]职业巡回赛回顾
2018/08/09 DOTA
利用Python-iGraph如何绘制贴吧/微博的好友关系图详解
2017/11/02 Python
django 在原有表格添加或删除字段的实例
2018/05/27 Python
无法使用pip命令安装python第三方库的原因及解决方法
2018/06/12 Python
python使用celery实现异步任务执行的例子
2019/08/28 Python
python 定义类时,实现内部方法的互相调用
2019/12/25 Python
基于python实现上传文件到OSS代码实例
2020/05/09 Python
Jogun Shop中文官网:韩国知名时尚男装网站
2016/10/12 全球购物
院药学专业个人求职信
2013/09/21 职场文书
销售文员岗位职责
2013/11/29 职场文书
生物学学生自我评价
2014/01/17 职场文书
应届毕业生自荐书
2014/06/18 职场文书
前台文员岗位职责
2015/02/04 职场文书
社区艾滋病宣传活动总结
2015/05/07 职场文书
教师读书活动心得体会
2016/01/14 职场文书