[英]Combine two python decorators into one
Here are two decorators I'd like to combine as they are pretty similar, the difference is how a not authenticated user is handled. 这里有两个我想要组合的装饰器,因为它们非常相似,区别在于如何处理未经过身份验证的用户。 I'd prefer to have one single decorator that I can call with an argument.
我更喜欢有一个可以用参数调用的装饰器。
# Authentication decorator for routes
# Will redirect to the login page if not authenticated
def requireAuthentication(fn):
def decorator(**kwargs):
# Is user logged on?
if "user" in request.session:
return fn(**kwargs)
# No, redirect to login page
else:
redirect('/login?url={0}{1}'.format(request.path, ("?" + request.query_string if request.query_string else '')))
return decorator
# Authentication decorator for routes
# Will return an error message (in JSON) if not authenticated
def requireAuthenticationJSON(fn):
def decorator(**kwargs):
# Is user logged on?
if "user" in request.session:
return fn(**kwargs)
# No, return error
else:
return {
"exception": "NotAuthorized",
"error" : "You are not authorized, please log on"
}
return decorator
And currently I'm using these decorators for specific routes, eg 目前我正在将这些装饰器用于特定路线,例如
@get('/day/')
@helpers.requireAuthentication
def day():
...
@get('/night/')
@helpers.requireAuthenticationJSON
def night():
...
I'd much more prefer this: 我更喜欢这个:
@get('/day/')
@helpers.requireAuthentication()
def day():
...
@get('/night/')
@helpers.requireAuthentication(json = True)
def night():
...
I'm on python 3.3 using the Bottle framework. 我在使用Bottle框架的python 3.3上。 Is it possible to do what I want?
有可能做我想要的吗? How?
怎么样?
Just add another wrapper to capture the json
parameter: 只需添加另一个包装器来捕获
json
参数:
def requireAuthentication(json=False):
def decorator(fn):
def wrapper(**kwargs):
# Is user logged on?
if "user" in request.session:
return fn(**kwargs)
# No, return error
if json:
return {
"exception": "NotAuthorized",
"error" : "You are not authorized, please log on"
}
redirect('/login?url={0}{1}'.format(request.path, ("?" + request.query_string if request.query_string else '')))
return wrapper
return decorator
I've renamed your original requireAuthentication
function to decorator
(because that is what that function did, it decorated fn
) and renamed the old decorator
to wrapper
, the usual convention. 我已经将你原来的
requireAuthentication
函数重命名为decorator
(因为这就是那个函数所做的,它装饰了fn
)并将旧的decorator
命名为wrapper
,这是通常的约定。
Whatever you put after the @
is an expression, evaluated first to find the actual decorator function. 无论你在
@
之后放置什么表达式,首先要评估实际的装饰器功能。 @helpers.requireAuthentication()
means you want to call requireAuthentication
and it's return value is then used as the actual decorator for the function the @
line applies to. @helpers.requireAuthentication()
表示你想调用requireAuthentication
然后它的返回值被用作@
line适用的函数的实际装饰器。
You can create wrapper for both of these decorators: 您可以为这两个装饰器创建包装器:
def requireAuthentication(json=False):
if json:
return helpers.requireAuthenticationJSON
else:
return helpers.requireAuthentication
Or 要么
import functools
# Authentication decorator for routes
# Will redirect to the login page if not authenticated
def requireAuthentication(json=False):
def requireAuthentication(fn):
@functools.wraps(fn)
def decorator(*args, **kwargs):
# Is user logged on?
if "user" in request.session:
return fn(*args, **kwargs)
if json:
return {
"exception": "NotAuthorized",
"error" : "You are not authorized, please log on"
}
return redirect('/login?url={0}{1}'.format(request.path,
("?" + request.query_string if request.query_string else '')))
return decorator
return requireAuthentication
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.