小半个晚上只干了一件事,研究web.py里面的authenticated方法。
先看这个函数的注释:
"""Decorate methods with this to require that the user be logged in."""
所以基本这个很清楚了,假设你有一个handler,而这个handler中有一个方法调用需要用户已登录,例如:
class TrasactionManager: def getTransactionDetail(self, id): blahblahblah
我们需要保证只有已经登录的用户才能调用到getTransactionDetail方法,那么,使用authenticated这个装饰器,来保证这个函数被调用前tornado会做相应的检查,修改后如下:
class TrasactionManager: @authenticated def getTransactionDetail(self, id): blahblahblah
当然了,这是其然,其所以然本菜鸟研究了半天。。。
首先就对python中的decorator不熟,谷歌了一下,找了一篇文章(http://blog.donews.com/limodou/archive/2004/12/19/207521.aspx),大致了解了怎么回事:
- 首先authenticated是不带参数的(method)这个参数除外
- 其次所有decorator修饰的方法会被python解释器“预处理”,例如:
def simpleDecorator(method): print "This is a decorator" return method @simpleDecorator def simpleMethod(): print "This is a method been decorated"
这个例子里,simpleMethod会被预处理为simpleMethod = simpleDecorator(simpleMethod)
所以,前面前面的例子中,类TrasactionManager中的getTransactionDetail实际上会变成这样getTransactionDetail=authenticated(getTransactionDetail),嗯原理就是这样了,不过尼嘛authenticated里面又定义了一个用装饰器修饰的方法,这就绕了。。。。最后我整理了一下,整个decorating流程大致成了这样:
@authenticated def getTransactionDetail(self, id): ‘’‘logic to get the transaction detail information which is bundle to specific user''' check_transaction_detail_of_current_user_by_id getTransactionDetail = authenticated(getTransactionDetail) = (functools.wraps(getTransactionDetail))(authenticated.wrapper) = (update_wrapper(wrapper #这个wrapper是update_wrapper方法的parameter place holder, getTransactionDetail, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES))(authenticated.wrapper)
= update_wrapper(authenticated.wrapper,
getTransactionDetail, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES) = Mixin-ed authenticated.wrapper
老实说,看了update_wrapper代码,我觉得除了默认定义的这些个属性外(
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
),没觉得__dict__里面有啥有用的东西,嗯,大概是我修为还不够
所以呢,经过上面一番折腾,参考authenticated的源代码,我们可以认为,这个getTransactionDetail已经面目全非,变成了另外一个样子。。
def getTransactionDetail(self, id):
if not self.current_user:
if self.request.method in ("GET", "HEAD"):
url = self.get_login_url()
if "?" not in url:
if urlparse.urlsplit(url).scheme:
# if login url is absolute, make next absolute too
next_url = self.request.full_url()
else:
next_url = self.request.uri
url += "?" + urllib.urlencode(dict(next=next_url))
self.redirect(url)
return
raise HTTPError(403)
‘’‘logic to get the transaction detail information
which is bundle to specific user'''
check_transaction_detail_of_current_user_by_id
注意最后三行高亮的部分,这正是原getTransactionDetail方法的方法体,但在之前,则加入了验证用户已经登录的逻辑。
所以,举一反三,我们也可以设计出其他更加复杂的验证机制,例如只有site admin才能执行的函数(例如偷摸从客户账面转走1W元这样的)
顺便记录三篇据说是大湿的系列文章,好长。。。。留着以后看
http://blog.csdn.net/beckel/article/details/3585352