我正在尝试使用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
答案 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'