官方文档-中间件指南
中间件的作用就是可以拦截请求和响应
就是可以在调用视图前和在调用视图后,做一些其他事情。
自定义中间件
方式一
适用于 Django2.x
from django.shortcuts import HttpResponse
class RejectIpMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
remote_ip = request.META['REMOTE_ADDR']
print(f"接收到请求后 --> 我在这里呀{remote_ip}--》调用视图前")
# return HttpResponse(f"{request.META['REMOTE_ADDR']}")
response = self.get_response(request)
print("调用视图后--》我在这里呀--》返回页面前")
return response
方式二
兼容 Django1.1
from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class RejectIpMiddlewareMixin(MiddlewareMixin):
def __init__(self, get_response):
self.get_response = get_response
def process_request(self, request):
print("接收到请求后 --> 我在这里呀--》调用视图前")
def process_response(self, request, response):
print("调用视图后--》我在这里呀--》返回页面前")
return response
1. 应用中间件
中间件可以是任意的 .py
文件,可以放在项目任何可被导入的路径中。
比如可以把中间件放在
qfsite/MyMiddleware/test.py
文件中
接下来在项目的settings.py
中设置一下,注意位置
'MyMiddleware.test.RejectIpMiddleware'
test.py
import time
from django.shortcuts import HttpResponse
# 时间范围 3 秒
REJ_SECOND = 3
# 限定访问次数
REJ_LIMIT = 3
# 封闭时长
REJ_TIME = 10
# IP 列表
REJ_IP = {}
info = {
'count': '3 秒内范围的次数',
'access_time': '访问时间',
'rejected': '拒绝时长',
}
def reject_ip(ip):
if ip not in REJ_IP:
REJ_IP[ip] = {
'count': 1,
'access_time': int(time.time()),
'rejected': None
}
return None
# 程序走到这里时,增加访问次数 1 次
REJ_IP[ip]['count'] += 1
# 判断是否在 3 秒之内
if time.time() < REJ_IP[ip]['access_time'] + 3:
# 判断访问次数合法
if REJ_IP[ip]['count'] > REJ_LIMIT:
REJ_IP[ip]["rejected"] = int(time.time())
print("访问次数首次超限:",REJ_IP[ip]['count'])
return True
print("有了:",REJ_IP)
# 程序走的这里是 3 秒之外
else:
print("目的访问次数:",REJ_IP[ip]['count'])
rejected = REJ_IP[ip]["rejected"]
if rejected and time.time() < REJ_IP[ip]["rejected"] + REJ_TIME:
print("访问信息",REJ_IP[ip] )
return True
else:
# 3 秒之外了,并且没有被封,或者超出解禁时间范围的,
# 次数和时间都应该重新计算
print("来了老弟", REJ_IP, int(time.time()))
__tmp_d = {'count': 1,
'rejected': None,
'access_time': int(time.time())}
REJ_IP[ip].update(__tmp_d)
print("改过了", REJ_IP)
class RejectIpMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
remote_ip = request.META['REMOTE_ADDR']
# print(f"接收到请求后 --> 我在这里呀{remote_ip}--》调用视图前")
r = reject_ip(remote_ip)
if r:
return HttpResponse("访问受限")
response = self.get_response(request)
# print("调用视图后--》我在这里呀--》返回页面前")
return response
装饰器版本
装饰器
from functools import wraps
def reject_ip(func):
@wraps(func)
def wrapper(*args, **kwargs):
ip = args[1].META["REMOTE_ADDR"]
if ip not in REJ_IP:
REJ_IP[ip] = {
'count': 1,
'access_time': int(time.time()),
'rejected': None
}
return func(*args, **kwargs)
# 程序走到这里时,增加访问次数 1 次
REJ_IP[ip]['count'] += 1
# 判断是否在 3 秒之内
if time.time() < REJ_IP[ip]['access_time'] + 3:
# 判断访问次数合法
if REJ_IP[ip]['count'] > REJ_LIMIT:
REJ_IP[ip]["rejected"] = int(time.time())
print("访问次数首次超限:",REJ_IP[ip]['count'])
return HttpResponse(
"无权访问,",
status=403)
print("有了:",REJ_IP)
return func(*args, **kwargs)
# 程序走的这里是 3 秒之外
else:
print("目的访问次数:",REJ_IP[ip]['count'])
rejected = REJ_IP[ip]["rejected"]
if rejected and time.time() < REJ_IP[ip]["rejected"] + REJ_TIME:
print("访问信息",REJ_IP[ip], time.time() )
return HttpResponse(
"无权访问,",
status=403)
else:
# 3 秒之外了,并且没有被封,或者超出解禁时间范围的,
# 次数和时间都应该重新计算
print("来了老弟", REJ_IP, int(time.time()))
__tmp_d = {'count': 1,
'rejected': None,
'access_time': int(time.time())}
REJ_IP[ip].update(__tmp_d)
print("改过了", REJ_IP)
return func(*args, **kwargs)
return wrapper
中间件
class RejectIpMiddleware:
def __init__(self, get_response):
self.get_response = get_response
@reject_ip
def __call__(self, request):
response = self.get_response(request)
return response
写成类装饰器
class Profiled:
def __init__(self, func):
wraps(func)(self)
def __call__(self, *args, **kwargs):
ip = args[1].META["REMOTE_ADDR"]
if ip not in REJ_IP:
REJ_IP[ip] = {
'count': 1,
'access_time': int(time.time()),
'rejected': None
}
return self.__wrapped__(*args, **kwargs)
# 程序走到这里时,增加访问次数 1 次
REJ_IP[ip]['count'] += 1
# 判断是否在 3 秒之内
if time.time() < REJ_IP[ip]['access_time'] + 3:
# 判断访问次数合法
if REJ_IP[ip]['count'] > REJ_LIMIT:
REJ_IP[ip]["rejected"] = int(time.time())
print("访问次数首次超限:",REJ_IP[ip]['count'])
return HttpResponse(
"无权访问,",
status=403)
print("有了:",REJ_IP)
return self.__wrapped__(*args, **kwargs)
# 程序走的这里是 3 秒之外
else:
print("目的访问次数:",REJ_IP[ip]['count'])
rejected = REJ_IP[ip]["rejected"]
if rejected and time.time() < REJ_IP[ip]["rejected"] + REJ_TIME:
print("访问信息",REJ_IP[ip], time.time() )
return HttpResponse(
"无权访问,",
status=403)
else:
# 3 秒之外了,并且没有被封,或者超出解禁时间范围的,
# 次数和时间都应该重新计算
print("来了兄弟", REJ_IP, int(time.time()))
__tmp_d = {'count': 1, 'rejected': None,'access_time': int(time.time())}
REJ_IP[ip].update(__tmp_d)
print("改过了", REJ_IP)
return self.__wrapped__(*args, **kwargs)
def __get__(self, instance, cls):
if instance is None:
return self
else:
return types.MethodType(self, instance)
class RejectIpMiddleware:
def __init__(self, get_response):
self.get_response = get_response
@Profiled
def __call__(self, request):
# remote_ip = request.META['REMOTE_ADDR']
# if reject_ip(remote_ip):
# return HttpResponse(
# "无权访问,",
# status=403)
# return HttpResponse(f"{request.META['REMOTE_ADDR']}")
response = self.get_response(request)
return response