详解django自定义中间件处理
中间件是一个钩子框架,它们可以介入Django的请求和响应处理过程。它是一个轻量级、底层的插件系统,用于在全局修改Django的输入或输出。
每个中间件组件负责完成某个特定的功能
这里介绍的中间件方法适用于Django1.10以上
相关文件:djangomiddleware
Django基础中间件
django.utils.deprecation.py classMiddlewareMixin(object): def__init__(self,get_response=None): self.get_response=get_response super(MiddlewareMixin,self).__init__() def__call__(self,request): response=None ifhasattr(self,'process_request'): response=self.process_request(request) ifnotresponse: response=self.get_response(request) ifhasattr(self,'process_response'): response=self.process_response(request,response) returnresponse
以上为Django基础中间件源码,要习惯于看源码,上面的这段代码并不复杂,下面我们来一一解释。
def__init__(self,get_response=None): self.get_response=get_response super(MiddlewareMixin,self).__init__()
熟悉python类的都不陌生__init__方法,这里主要是一次性配置和初始化
def__call__(self,request): response=None ifhasattr(self,'process_request'): response=self.process_request(request) ifnotresponse: response=self.get_response(request) ifhasattr(self,'process_response'): response=self.process_response(request,response) returnresponse
__call__为每个请求/响应执行的代码
self.process_request(request)为每个请求到调用视图之前的操作,通常可以在这里做一些用户请求频率的控制。
self.get_response(request)为调用视图
self.process_response(request,response)为调用视图完成后的操作
自定义中间件
刚才了解了基础中间件,现在就开始编写我们自己的中间件。
通常我们回去继承基础中间件来实现自己的功能
fromdjango.utils.deprecationimportMiddlewareMixin classPermissionMiddlewareMixin(MiddlewareMixin): """ django中间件 """ defprocess_request(self,request): pass defprocess_response(self,request,response): returnresponse
如果你要在请求之前做处理,需要定义process_request()方法,去实现相关功能
如果你要在视图调用之后做处理,需要定义process_response()方法,去实现相关功能
:warning:注意定义process_response()方法一定要returnresponse
需要将你编写的中间件添加到settings中的MIDDLEWARE里
我这里写了一个通过中间件限制客户端请求频率,有兴趣的可以看一下
django中间件客户端请求频率限制
通过redislua脚本对客户端IP请求频率限制
#coding:utf-8 __author__='carey@akhack.com' fromdjango.utils.deprecationimportMiddlewareMixin fromdjango.http.responseimportHttpResponse fromdjango_redisimportget_redis_connection fromhashlibimportmd5 classRequestBlockMiddlewareMixin(MiddlewareMixin): """ django中间件客户端请求频率限制 """ limit=4#单位时间内允许请求次数 expire=1#限制时间 cache="default"#获取djangocache defprocess_request(self,request): num=self.set_key(request) ifnum>self.limit: returnHttpResponse("请求频率过快,请稍后重试",status=503) @staticmethod defget_ident(request): """ IdentifythemachinemakingtherequestbyparsingHTTP_X_FORWARDED_FOR ifpresentandnumberofproxiesis>0.Ifnotuseallof HTTP_X_FORWARDED_FORifitisavailable,ifnotuseREMOTE_ADDR. """ NUM_PROXIES=1 xff=request.META.get('HTTP_X_FORWARDED_FOR') remote_addr=request.META.get('REMOTE_ADDR') num_proxies=NUM_PROXIES ifnum_proxiesisnotNone: ifnum_proxies==0orxffisNone: returnremote_addr addrs=xff.split(',') client_addr=addrs[-min(num_proxies,len(addrs))] returnclient_addr.strip() return''.join(xff.split())ifxffelseremote_addr defget_md5(self,request): """ 获取IPmd5值 :paramrequest: :return: """ ip_str=self.get_ident(request) ip_md5=md5() ip_md5.update(ip_str.encode("utf-8")) returnip_md5.hexdigest() defset_key(self,request): """ 通过redislua脚本设置请求请求次数和限制时间 :paramrequest: :return:限制时间内请求次数 """ lua=""" localcurrent current=redis.call("incr",KEYS[1]) iftonumber(current)==1then redis.call("expire",KEYS[1],ARGV[1]) end returntonumber(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) returndata
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。