例如,我在模块a
上有一个声明性类:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
addresses = relationship("Address", backref="user")
现在,在模块b
中,我想使用映射的实体,但添加一个方法:
from a import User
class UserWithExtraMethod(User):
def name_capitalized(self):
return self.name.capitalize()
user = UserWithExtraMethod()
print(user.name_capitalized)
但是,当我运行脚本时,我会收到以下错误:
InvalidRequestError: Multiple classes found for path "User" in the registry of this declarative base. Please use a fully module-qualified path.
宣布用户实体时我错过了什么?我想重用之前声明的实体。
我期待有些事情会像:
class UserWithExtraMethod(User):
___magic_reuse_previous_mapper__ = True
def name_capitalized(self):
return self.name.capitalize()
答案 0 :(得分:3)
这个回复可能有点晚了。您是否有任何其他关系设置指向User
?
例如,如果您将Address
定义为:
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
address = Column(String(50))
Users = relationship("User", backref="addresses")
当Address
试图解析声明性基础中的哪个用户指向时,它会找到其中两个。要验证尝试Base._decl_class_registry['User']
。这类似于Michael所涵盖的this主题。
在./sqlalchemy/ext/declarative/clsregistry.py
中有一个关于如何使用完全限定路径的示例。在这种情况下,它会将地址内的关系从Users = relationship("User", backref="addresses")
更改为
Users = relationship("a.User", backref="addresses")
希望这有助于指出正确的调试方向。
答案 1 :(得分:2)
除非你有特别的理由要有单独的类,否则你应该写一下:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
addresses = relationship("Address", backref="user")
def name_capitalized(self):
return self.name.capitalize()
由于name_capitalized
就SQLAlchemy而言并不特殊(它不是ColumnExpression
或某些此类),因此映射器完全忽略它。
实际上,有更好的方法可以做到这一点;你的版本适用于User
的实例,但在sql表达式中没用。
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
class User(Base):
# ... body as before
@hybrid_method
def name_capitalized(self):
return self.name.capitalize()
@name_capitalized.expression
def name_capitalized(cls):
# works for postgresql, other databases spell this differently.
return sqlalchemy.func.initcap(cls.name)
允许您执行以下操作:
>>> print Query(User).filter(User.name_capitalized() == "Alice")
SELECT users.id AS users_id, users.name AS users_name
FROM users
WHERE initcap(users.name) = :initcap_1
答案 2 :(得分:1)
Hacky,但为什么不为了你的目的而修补User
类而不是继承它呢?
# modude b
from a import User
def name_capitalized(self):
return self.name.capitalize()
User.name_capitalized = name_capitalized
user = User() # and it has extra-method as well
print(user.name_capitalized)
答案 3 :(得分:0)
这可能不适合您。我有一个类似的问题。我最终在实例化期间将User的实例传递给UserWithExtraMethod
class UserWithExtraMethod(object):
def __init__(self, user):
self.user = user
def name_capitalized(self):
return self.user.name.capitalize()
希望这有帮助