详解Python的Django框架中的中间件
什么是中间件
我们从一个简单的例子开始。
高流量的站点通常需要将Django部署在负载平衡proxy之后。这种方式将带来一些复杂性,其一就是每个request中的远程IP地址(request.META["REMOTE_IP"])将指向该负载平衡proxy,而不是发起这个request的实际IP。负载平衡proxy处理这个问题的方法在特殊的X-Forwarded-For中设置实际发起请求的IP。
因此,需要一个小小的中间件来确保运行在proxy之后的站点也能够在request.META["REMOTE_ADDR"]中得到正确的IP地址:
classSetRemoteAddrFromForwardedFor(object): defprocess_request(self,request): try: real_ip=request.META['HTTP_X_FORWARDED_FOR'] exceptKeyError: pass else: #HTTP_X_FORWARDED_FORcanbeacomma-separatedlistofIPs. #Takejustthefirstone. real_ip=real_ip.split(",")[0] request.META['REMOTE_ADDR']=real_ip
(Note:AlthoughtheHTTPheaderiscalledX-Forwarded-For,Djangomakesitavailableasrequest.META['HTTP_X_FORWARDED_FOR'].Withtheexceptionofcontent-lengthandcontent-type,anyHTTPheadersintherequestareconvertedtorequest.METAkeysbyconvertingallcharacterstouppercase,replacinganyhyphenswithunderscoresandaddinganHTTP_prefixtothename.)
一旦安装了该中间件(参见下一节),每个request中的X-Forwarded-For值都会被自动插入到request.META['REMOTE_ADDR']中。这样,Django应用就不需要关心自己是否位于负载平衡proxy之后;简单读取request.META['REMOTE_ADDR']的方式在是否有proxy的情形下都将正常工作。
实际上,为针对这个非常常见的情形,Django已将该中间件内置。它位于django.middleware.http中,下一节将给出这个中间件相关的更多细节。
安装中间件
要启用一个中间件,只需将其添加到配置模块的MIDDLEWARE_CLASSES元组中。在MIDDLEWARE_CLASSES中,中间件组件用字符串表示:指向中间件类名的完整Python路径。例如,下面是django-admin.pystartproject创建的缺省MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES=( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', )
Django项目的安装并不强制要求任何中间件,如果你愿意,MIDDLEWARE_CLASSES可以为空。
这里中间件出现的顺序非常重要。在request和view的处理阶段,Django按照MIDDLEWARE_CLASSES中出现的顺序来应用中间件,而在response和异常处理阶段,Django则按逆序来调用它们。也就是说,Django将MIDDLEWARE_CLASSES视为view函数外层的顺序包装子:在request阶段按顺序从上到下穿过,而在response则反过来。