中间件介绍
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
每个中间件都会负责一个功能,例如,AuthenticationMiddleware,与sessions处理相关。
激活中间件
需要在settings.py配置文件中,配置MIDDLEWARE_CLASSES:
1
2
3
4
5
6
7
8
9
10
|
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware' ,
'django.middleware.common.CommonMiddleware' ,
'django.middleware.csrf.CsrfViewMiddleware' ,
'django.contrib.auth.middleware.AuthenticationMiddleware' ,
'django.contrib.auth.middleware.SessionAuthenticationMiddleware' ,
'django.contrib.messages.middleware.MessageMiddleware' ,
'django.middleware.clickjacking.XFrameOptionsMiddleware' ,
]
|
当然你也可以不试用任何的中间件,这个可以设置为空。
中间件顺序
一般我们我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下,process request 和 process response的执行顺序正好相反,如下图所示:
也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。
中间件不用继承自任何类(可以继承 object ),下面一个中间件大概的样子:
1
2
3
4
5
6
|
class CommonMiddleware( object ):
def process_request( self , request):
return None
def process_response( self , request, response):
return response
|
需要用到的几个hook:
- process_request()
- process_exception() (only if the view raised an exception)
- process_template_response()
- process_response()
常用的中间件组件:
1. Sessions
2. Authentication
3. CSRF Protection
4. GZipping Content
例如,比如我们要做一个 流量统计
1
2
3
4
5
|
class BlockedIpMiddleware( object ):
def process_request( self , request):
...数据库拿access值
access = access + 1
...存起来,类似这个原理
|
这里的代码的功能就是 简单的访问一次加一次,把这个中间件的 Python 路径写到settings.py中
1
2
3
4
|
MIDDLEWARE_CLASSES = (
'zjj.middleware.BlockedIpMiddleware' ,
...其它的中间件
)
|
Django 会从 MIDDLEWARE_CLASSES 中按照从上到下的顺序一个个执行中间件中的 process_request 函数,而其中 process_response 函数则是最前面的最后执行。
二,再比如,我们在网站放到服务器上正式运行后,DEBUG改为了 False,这样更安全,但是有时候发生错误不能显示错误详情页面,有没有办法处理好这两个事情呢?
普通访问者看到的是友好的报错信息
管理员看到的是错误详情,以便于修复 BUG
当然可以有,利用中间件就可以做到!代码如下:
1
2
3
4
5
6
7
8
|
import sys
from django.views.debug import technical_500_response
from django.conf import settings
class UserBasedExceptionMiddleware( object ):
def process_exception( self , request, exception):
if request.user.is_superuser or request.META.get( 'REMOTE_ADDR' ) in settings.INTERNAL_IPS:
return technical_500_response(request, * sys.exc_info())
|
把这个中间件像上面一样,加到你的 settings.py 中的 MIDDLEWARE_CLASSES 中,可以放到最后,这样可以看到其它中间件的 process_request的错误。
当访问者为管理员时,就给出错误详情,比如访问本站的不存在的页面。
普通人看到的是普通的 404(自己点开看看),而我们却可以看到。
三,分享一个简单的识别手机的中间件,更详细的可以参考这个:django-mobi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
MOBILE_USERAGENTS = ( "2.0 MMP" , "240x320" , "400X240" , "AvantGo" , "BlackBerry" ,
"Blazer" , "Cellphone" , "Danger" , "DoCoMo" , "Elaine/3.0" , "EudoraWeb" ,
"Googlebot-Mobile" , "hiptop" , "IEMobile" , "KYOCERA/WX310K" , "LG/U990" ,
"MIDP-2." , "MMEF20" , "MOT-V" , "NetFront" , "Newt" , "Nintendo Wii" , "Nitro" ,
"Nokia" , "Opera Mini" , "Palm" , "PlayStation Portable" , "portalmmm" , "Proxinet" ,
"ProxiNet" , "SHARP-TQ-GX10" , "SHG-i900" , "Small" , "SonyEricsson" , "Symbian OS" ,
"SymbianOS" , "TS21i-10" , "UP.Browser" , "UP.Link" , "webOS" , "Windows CE" ,
"WinWAP" , "YahooSeeker/M1A1-R2D2" , "iPhone" , "iPod" , "Android" ,
"BlackBerry9530" , "LG-TU915 Obigo" , "LGE VX" , "webOS" , "Nokia5800" )
class MobileTemplate( object ):
"""
If a mobile user agent is detected, inspect the default args for the view
func, and if a template name is found assume it is the template arg and
attempt to load a mobile template based on the original template name.
"""
def process_view( self , request, view_func, view_args, view_kwargs):
if any (ua for ua in MOBILE_USERAGENTS if ua in
request.META[ "HTTP_USER_AGENT" ]):
template = view_kwargs.get( "template" )
if template is None :
for default in view_func.func_defaults:
if str (default).endswith( ".html" ):
template = default
if template is not None :
template = template.rsplit( ".html" , 1 )[ 0 ] + ".mobile.html"
try :
get_template(template)
except TemplateDoesNotExist:
pass
else :
view_kwargs[ "template" ] = template
return view_func(request, * view_args, * * view_kwargs)
return None
|
再举一个本地化的中间件的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class LocaleMiddleware( object ):
def process_request( self , request):
if 'locale' in request.cookies:
request.locale = request.cookies.locale
else :
request.locale = None
def process_response( self , request, response):
if getattr (request, 'locale' , False ):
response.cookies[ 'locale' ] = request.locale
|
就是将cookies中的locale设置给request中的locale,供给后面使用。
这部分参考了django官方文档以及网络上的一些教程,这里也非常感谢这些前辈的分享。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://blog.csdn.net/alvine008/article/details/50249777