中间件是一个钩子框架,它们可以介入 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]