设置时SQLAlchemy hybrid_property错误

时间:2014-02-18 15:27:04

标签: python sqlalchemy pylons getter-setter

我正在尝试使用hybrid_property装饰器来定义getter / setter。这是代码。

class Users(object):
def __init__(self, username, uid=None, password=None, group_uid=None):
    self.uid = uid
    self.username = username
    self.password = password
    self.group_uid = group_uid

def __repr__(self):

    return "User(%(username)s)" % self.__dict__

@hybrid_property
def password(self):

    return self._password

@password.setter
def set_password(self, password):       

    self._password = password

当查看用户对象时,getter正常工作,即user.password返回一个字符串,但调用setter会产生以下内容

user.test('test')
Traceback (most recent call last):
  File "--removed--", line 35, in exec_expr
    exec code in self.namespace, self.globs
  File "<web>", line 1, in <module>
TypeError: 'str' object is not callable

任何帮助指出我缺少的东西都将不胜感激。

PS。使用SQLAlchemy版本0.9.1

4 个答案:

答案 0 :(得分:1)

我还没有深入了解SQLAlchemy代码,明确地说这是问题所在,但我的打赌是你正在使用不正确的属性。 set_password应该被称为password。我打赌它会解决你的问题,但即使它没有,你仍然需要这样做。 See this example.

您将使用内置@property装饰器看到相关错误。请记住,装饰器只是简单地分配函数的结果,该函数接受并将可调用的函数返回到本地命名空间中的装饰函数的标签。你在这里做的是创建一个可调用的并将其分配给password,然后创建一个新的可调用来包装password可调用并将其分配给set_password。您在评论中提到它适用于较旧版本的SQLAlchemy。我敢打赌,在使用my_var.setter返回新实例时,他们从修改包装的可调用对象切换。如果您使用set_password,则很可能会按预期password工作。

答案 1 :(得分:1)

原始模型使用的是经典映射样式。重构模型以使用Declarative Mapping样式修复了问题。我猜混合属性仅在类使用Declarative base时才起作用。

答案 2 :(得分:1)

这不起作用的原因是(我怀疑)因为您正在测试该属性,就好像它是一种方法。从您的测试代码user.test()开始(我假设代码的某些版本password被称为test

如果你执行user.password('changeme'),那么它将无效,因为user.password不是一种方法。相反它应该是:user.password = 'changeme'

我认为切换到声明基础可能只是巧合。

答案 3 :(得分:0)

我只想把它放在这里给那些有兴趣的人... 尝试在Airflow中创建密码时,我也遇到了这个问题。似乎是Airflow中sqlalchemy版本的兼容性问题。我安装了它并解决了问题:pip install'sqlalchemy <1.2'