2017-03-04 66 views
0

对不起书呆子的问题,但我花了2天,但找不到任何解决方案。在python中使用@cached_property请求处理程序与python

这是我route.py配置

app = WSGIApplication(
    routes=[ 
     Route("/account", handler="app.account.Settings") 
    ] 
) 

我创建了一个这样的处理程序(这需要登录)

@HealthPortRequestHandler.login_required 
class Settings(HealthPortRequestHandler): 
    def get(self): 
     self.render("account/settings.html") 

,创造login_required验证方法

@cached_property 
    def check_user_logged_in(self): 
     if self.request.cookies.get("User"): 
      user_id = self.read_cookie("User") 
      if user_id: 
       from models.users import Users 
       return Users.get_by_id(int(user_id)) 
      else: 
       return None 
     return None 

    @staticmethod 
    def login_required(handler): 
     def check_login(self, *args, **kwargs): 
      if self.check_user_logged_in: 
       return handler(self, *args, **kwargs) 
      else: 
       return self.redirect("/login") 
     return check_login 

但错误在此线路上调试时发现

if self.check_user_logged_in: 

错误 提高AttributeError的(attr)使用

AttributeError: check_user_logged_in 

怎样才能知道究竟发生了什么?有任何想法吗 ?

回答

1

您正在将装饰器login_required应用于类Settings,所以装饰器将在创建Settings实例时执行。

当您尝试创建Settings的实例时,login_required中的check_login函数被调用。它收到的参数是传递给Setting__init__方法的值。 check_login然后将其收到的第一个值作为参数并尝试访问其属性check_user_logged_in。这个值,无论它是什么(可能是一个webapp2.Request对象),都没有check_user_logged_in属性,所以引发异常。

这可以在不使用webapp2的框架来证明:

class HealthPortRequestHandler(object): 

    def __init__(self, *args, **kwargs): 
     pass 

    @property 
    def check_user_logged_in(self): 
     pass 

    @staticmethod 
    def login_required(handler): 
     def check_login(self, *args, **kwargs): 
      if self.check_user_logged_in: 
       return handler(self, *args, **kwargs) 
      else: 
       raise RuntimeError('Not expecting to execute this') 
     return check_login 


@HealthPortRequestHandler.login_required 
class Settings(HealthPortRequestHandler): 
    pass 

>>> s = Settings('Hello') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "demo.py", line 14, in check_login 
    if self.check_user_logged_in: 
AttributeError: 'str' object has no attribute 'check_user_logged_in' 

>>> s = Settings(5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "demo.py", line 14, in check_login 
    if self.check_user_logged_in: 
AttributeError: 'int' object has no attribute 'check_user_logged_in' 

>>> s = Settings('Hello', 5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "deco.py", line 14, in check_login 
    if self.check_user_logged_in: 
AttributeError: 'str' object has no attribute 'check_user_logged_in' 

所以这就是为什么你的AttributeError的。

为了解决它,我建议装饰请求处理程序的调度方法,而不是类定义。通过这种方式,您仍然可以在处理请求之前进行检查,但可以访问完全初始化的Settings实例。

+0

但无论如何,我固定我的代码为你的建议: '类设置(HealthPortRequestHandler): @ HealthPortRequestHandler.login_required 高清得到(个体经营): self.render( “帐号/ settings.html”) ' – user2165201