我在Google的AppEngine中使用python函数装饰器时遇到了麻烦。我不熟悉装饰器,但是当你想要强制用户在执行某些功能之前登录时,它们在web编程中似乎很有用。
无论如何,我跟着一个使用django的flickr登录示例here并装饰一个函数来要求flickr登录。我似乎无法在AppEngine中使用这种类型的装饰器。
我把它归结为:
def require_auth(func):
def check_auth(*args, **kwargs):
print "Authenticated."
return func(*args, **kwargs)
return check_auth
@require_auth
def content():
print "Release sensitive data!"
content()
此代码适用于命令行,但是当我在GoogleAppEngineLauncher(OS X)中运行时,我收到以下错误:
check_auth() takes at least 1 argument (0 given)
我不确定为什么......
编辑以包含实际代码: @ asperous.us我改变了content()的定义来包含变量参数,那是什么意思? @Alex Martelli,'print'在AppEngine中工作,但仍然是一个完全公平的批评。 就像我说的,我正在尝试使用上面链接中的flickr登录。我试着将它放入我的应用程序中:
def require_flickr_auth(view):
def protected_view(request,*args, **kwargs):
if 'token' in request.session:
token = request.session['token']
log.info('Getting token from session: %s' % token)
else:
token = None
log.info('No token in session')
f = flickrapi.FlickrAPI(api_key, api_secret,
token=token, store_token=False)
if token:
# We have a token, but it might not be valid
log.info('Verifying token')
try:
f.auth_checkToken()
except flickrapi.FlickrError:
token = None
del request.session['token']
if not token:
# No valid token, so redirect to Flickr
log.info('Redirecting user to Flickr to get frob')
url = f.web_login_url(perms='read')
print "Redirect to %s" % url
# If the token is valid, we can call the decorated view.
log.info('Token is valid')
return view(request,*args, **kwargs)
return protected_view
@require_flickr_auth
def content(*args, **kwargs):
print 'Welcome, oh authenticated user!'
def main():
print 'Content-Type: text/plain'
content()
if __name__ == "__main__":
main()
当我删除@require_flickr_auth装饰时,字符串'Welcome ...'打印出来就好了。否则我会得到一个带有
的丑陋的AppEngine异常页面type 'exceptions.TypeError': protected_view() takes at least 1 argument (0 given)
在底部。
答案 0 :(得分:3)
您在没有任何参数的情况下调用content()
,但装饰版本protected_view
需要request
参数。将参数添加到content
或将其从protected_view
中删除。
如果您的简单版本出现错误,那么我怀疑content
是Alex建议的类方法。否则看起来你要告诉它至少有一个参数,然后不提供它。
答案 1 :(得分:1)
@Owen,“至少需要一个参数”错误表明你在一个类中定义内容(即作为一个方法)而不是你所展示的裸函数 - 实际上,你究竟是如何执行的GAE中的代码?即什么是你的app.yaml& c?如果您完全按照silly.py
和app.yaml中提供的代码放置代码,则可以:
handlers:
- url: /silly
script: silly.py
然后当你访问yourapp.appspot.com/silly
时,你会在浏览器或日志上看到什么都没有(当然除了后面的"GET /silly HTTP/1.1" 200 -
;-):没有错误,但是{{1也没有特别做任何事情。所以我必须想象你尝试运行与你向我们展示的代码不同的代码......! - )
答案 2 :(得分:0)
在Python 2.4(我认为)中添加了装饰器,也许googleapp使用的是旧版本? 你也可以这样做:
def content():
print "Release sensitive data!"
content = require_auth(content)
它将与装饰器做同样的事情,它只是更多的工作。
答案 3 :(得分:0)
为什么
return func(*args, **kwargs)
不会执行func然后返回结果吗?
如果是这样,你不应该给它任何论据,因为它不需要任何参数。如果你编辑了content()并在其上添加了(*args, **kwargs)
个参数,它会起作用吗?