Sqlalchemy、继承与关系
我有一个通用的用户对象,这个对象是我网站的基础类,使用了连接表的方式来构建。
class User(Base):
__tablename__ = "auth_user"
id = Column(Integer, primary_key = True)
username = Column(String(100), nullable = False, unique = True, index = True)
...
type = Column(String(1))
__mapper_args__ = {'polymorphic_on' : type, "extension" : HashExtension()}
然后我基于这个类创建了一个员工对象。
class Staff(User):
__tablename__ = "auth_staff"
__mapper_args__ = {'polymorphic_identity' : 's'}
id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)
现在我又有一个候选人对象,同样是从用户对象派生出来的。
class Candidate(User):
__tablename__ = "candidates_candidate"
__mapper_args__ = {'polymorphic_identity' : 'c'}
id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)
...
staff_id = Column(Integer, ForeignKey("auth_user.id"), nullable = False)
staff = relationship("Staff", backref = backref("candidates", order_by = id))
到目前为止,候选人对象的部分都没问题。我想让它能链接回员工对象,但我遇到了关于没有“primaryjoin”的错误,我对这个关系应该如何链接到员工对象感到困惑——是不是应该链接到用户对象,因为员工是从用户派生的呢?……
任何建议我都会非常感激。
~~~~~~~~~更新 2月3日~~~~~~~~~~~~~~
修订后的代码 - 仍然抛出关于primaryjoin的错误。如果我添加了primaryjoin,它还是会出错。
#!/usr/bin/env python
from sqlalchemy import Column, Integer, String, ForeignKey, Boolean
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
class DomainBase(object):
active = Column(Boolean, default = True, nullable = False)
def __str__(self):
return repr(self)
Base = declarative_base(cls = DomainBase)
class User(Base):
__tablename__ = "auth_user"
id = Column(Integer, primary_key = True)
username = Column(String(100), nullable = False, unique = True, index = True)
type = Column(String(1))
__mapper_args__ = {'polymorphic_on' : type}
class Staff(User):
__tablename__ = "auth_staff"
__mapper_args__ = {'polymorphic_identity' : 's'}
id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)
class Candidate(User):
__tablename__ = "candidates_candidate"
__mapper_args__ = {'polymorphic_identity' : 'c'}
id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)
staff_id = Column(Integer, ForeignKey("auth_staff.id"), nullable = False)
staff = relationship("Staff", backref = backref("candidates", order_by = id))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind = engine, autocommit=True)
session = Session()
with session.begin():
s = Staff(username = "DaveSmith")
session.add_all([s])
1 个回答
4
你的例子中使用了两个外键指向基类表,所以 SQLAlchemy 无法判断 1) 应该用哪个外键来进行继承连接,2) 应该用哪个外键来处理员工关系。你需要为这两种情况提供提示。第一个情况需要在 __mapper_args__
中设置 'inherit_condition'
选项(更多信息可以查看这个回答),第二个情况则需要在 relationship
中添加 primaryjoin=(staff_id==User.id)
参数。
但是要注意,你的 staff
关系是指向 Staff
类的,而 staff_id
是指向 User
表的外键。虽然你可能有某种理由这样做,但在大多数情况下这样并不好。将 staff_id
的定义改为使用 ForeignKey("auth_staff.id")
可以解决你的问题,而不需要其他更改。