在tornado项目中一些RequestHandler中的get(),post()方法需要验证登陆用户和用户权限,并返回template或者json。
class IndexHandler(RequestHandler):
@render_json
@login_required
@permission_required(10001)
get(self):
pass
对于同一个get()方法使用了多个装饰器,运行的顺序一般是自上而下,但太多个装饰器个人认为还是比较难以理解。
Demo
def first_decorator(func):
print('--first--')
def first_wrapper(*args, **kwargs):
print('------first---%s---' % func.__name__)
return func(*args, **kwargs)
return first_wrapper
def second_decorator(func):
print('--second--')
def second_wrapper(*args, **kwargs):
print('------second---%s---' % func.__name__)
return func(*args, **kwargs)
return second_wrapper
@first_decorator
@second_decorator
def test_func_1():
print('excute %s' % inspect.stack()[0][3])
定义了两个装饰器,并装饰了函数test_func_1(),此时应该输出:
--second--
--first--
------first---second_wrapper---
------second---test_func_1---
excute test_func_1
拆分装饰器@语法糖以后,等价于。
def test_func_1():
print('excute %s' % inspect.stack()[0][3])
first_decorator(second_decorator(test_func_1))()
进一步拆分。
second_wrapper = second_decorator(test_func_1) # 返回实际是second_wrapper
# second()
first = first_decorator(second_wrapper) # second_wrapper 传入first_decorator()
first()
实际上首先执行了second_decorator(test_func_1)
返回second_wrapper
函数,而此时--second--
已经打印了。
然后first_decorator()
接受之前返回的second_wrapper
并返回了first_wrapper
函数,而此时--first--
已经打印了。
最后执行first_wrapper(second_wrapper)()
,先打印出------first---second_wrapper---
了,因为此时first_decorator
中接受的func
是second_wrapper
,然后执行func(*args, **kwargs)
即second_wrapper()
,打印出------second---test_func_1---
,最后执行test_func_1()
,打印excute test_func_1
(感觉仍有问题,需要重新整理一下思路。)
模拟Handler
def login_required(func):
def wrapper(self, *args, **kwargs):
if not self.current_user:
# 未登录情况
raise Exception('please login')
else:
return func(self, *args, **kwargs)
return wrapper
def permission_required(permission_code):
def decorator(func):
def wrapper(self, *args, **kwargs):
if not self.current_user.permission_code == permission_code:
raise Exception('not have permission')
else:
return func(self, *args, **kwargs)
return wrapper
return decorator
class User():
def __init__(self, name, permission_code=0):
self.name = name
self.permission_code = permission_code
class BaseHandler():
def __init__(self, current_user=None):
self.current_user = current_user
@login_required
@permission_required(1)
def get(self):
print('get success')
return 'hello'
@permission_required(1)
@login_required
def post(self):
print('post success')
return 'hello'
是否能简化成一个装饰器?
# 简化成一个装饰器?
def check_login_permission(permission_code=0):
# 0默认不需要权限
def decorator(func):
def wrapper(self, *args, **kwargs):
if not self.current_user:
raise Exception('please login')
if permission_code and self.current_user.permission_code != permission_code:
raise Exception('not have permission')
return func(self, *args, **kwargs)
return wrapper
return decorator
class NewBaseHandler():
def __init__(self, current_user=None):
self.current_user = current_user
@check_login_permission(0)
def get(self):
print('get success')
return 'hello'
try:
# user_1 = User('JiangW_1', 1)
# new_base_handler = NewBaseHandler(user_1)
new_base_handler = NewBaseHandler(None)
new_base_handler.get()
except Exception as e:
print(e)