Sqlalchemy,继承和关系

时间:2011-02-01 16:09:03

标签: python sql 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()}

然后我有一个基于这个类的Staff对象


class Staff(User):
    __tablename__ = "auth_staff"
    __mapper_args__ = {'polymorphic_identity' : 's'}    
    id = Column(Integer, ForeignKey('auth_user.id'), primary_key = True)

现在我还有一个Candidate对象,再次派生自User


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))

在候选对象结束时一切正常。我希望它链接回一个Staff对象,但是我收到的错误是没有'primaryjoin'而且我对这个关系应该如何链接到Staff对象感到困惑 - 如果它链接到User对象作为Staff派生从它?....

任何建议都会感激不尽

2月2日更新~~~~~~~~~~~~~~

修订后的代码 - 仍会抛出有关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 个答案:

答案 0 :(得分:3)

您的示例使用2个外键来基类表,因此SQLAlchemy无法确定1)什么外键应该用于继承连接,2)用于员工关系的外键。您必须为两种情况指定提示。前者需要'inherit_condition'中的__mapper_args__选项(请参阅此answer for more info),稍后需要primaryjoin=(staff_id==User.id) relationship的参数。

但请注意,您的staff关系引用了Staff类,而staff_id有外键引用User的表。虽然你的移民有一些共鸣,但在大多数情况下并不好。 更改staff_id定义以使用ForeignKey("auth_staff.id")将解决您的问题,而无需进行其他更改。