详解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基础入门详解(文件输入/输出 内建类型 字典操作使用方法)
Dec 08 Python
python构造icmp echo请求和实现网络探测器功能代码分享
Jan 10 Python
一则python3的简单爬虫代码
May 26 Python
Python-基础-入门 简介
Aug 09 Python
Python简单生成8位随机密码的方法
May 24 Python
教你利用Python玩转histogram直方图的五种方法
Jul 30 Python
使用python实现语音文件的特征提取方法
Jan 09 Python
简单了解python单例模式的几种写法
Jul 01 Python
6行Python代码实现进度条效果(Progress、tqdm、alive-progress​​​​​​​和PySimpleGUI库)
Jan 06 Python
基于Python和PyYAML读取yaml配置文件数据
Jan 13 Python
Django vue前后端分离整合过程解析
Nov 20 Python
Python FuzzyWuzzy实现模糊匹配
Apr 28 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
德生BCL3000的电路分析和打磨
2021/03/02 无线电
浅析PHP程序防止ddos,dns,集群服务器攻击的解决办法
2013/06/18 PHP
php中strtotime函数用法详解
2014/11/15 PHP
PHP设计模式之委托模式定义与用法简单示例
2018/08/13 PHP
PHP的mysqli_stmt_init()函数讲解
2019/01/24 PHP
javascript判断单选框或复选框是否选中方法集锦
2007/04/04 Javascript
js修改input的type属性及浏览器兼容问题探讨与解决
2013/01/23 Javascript
jQuery实现数秒后自动提交form的方法
2015/03/05 Javascript
异步安全加载javascript文件的方法
2015/07/21 Javascript
微信小程序 input输入框详解及简单实例
2017/01/10 Javascript
jquery 手势密码插件
2017/03/17 Javascript
Angular4实现图片上传预览路径不安全的问题解决
2017/12/25 Javascript
关于Vue的路由权限管理的示例代码
2018/03/06 Javascript
Ant Design Vue 添加区分中英文的长度校验功能
2020/01/21 Javascript
vue a标签点击实现赋值方式
2020/09/07 Javascript
JavaScript 闭包的使用场景
2020/09/17 Javascript
[02:09]抵达西雅图!中国军团加油!
2014/07/07 DOTA
python计算牛顿迭代多项式实例分析
2015/05/07 Python
Windows下为Python安装Matplotlib模块
2015/11/06 Python
如何在Python中编写并发程序
2016/02/27 Python
Python 编码规范(Google Python Style Guide)
2018/05/05 Python
python操作mysql代码总结
2018/06/01 Python
Python3.6基于正则实现的计算器示例【无优化简单注释版】
2018/06/14 Python
使用Python实现文字转语音并生成wav文件的例子
2019/08/08 Python
关于HTML5+ API plusready的兼容问题
2020/11/20 HTML / CSS
Expedia挪威官网:酒店、机票和租车
2018/03/03 全球购物
物流专业毕业生推荐信范文
2013/11/18 职场文书
就业自荐书
2013/12/05 职场文书
培训心得体会
2013/12/29 职场文书
爱情保证书范文
2014/02/01 职场文书
《浅水洼里的小鱼》听课反思
2014/02/28 职场文书
社区消防工作实施方案
2014/03/21 职场文书
三年级小学生评语
2014/04/22 职场文书
区域销售主管岗位职责
2014/06/15 职场文书
2014业务员年终工作总结
2014/12/09 职场文书
初二数学教学反思
2016/02/17 职场文书