【问题标题】:SQLAlchemy declared_attr on Column with Foreign KeySQLAlchemy declared_attr on Column with Foreign Key
【发布时间】:2021-06-29 04:13:52
【问题描述】:

我有一个设置,我正在使用一个抽象的机器基类,它有几个用于不同类型机器的子类。原因是我想为这些机器使用不同的数据库模式,它们有一些相似但有些完全不同的表。

class Machine(Base):
    __abstract__ = True
    __tablename__ = 'machines'

    id = Column('id', BigInteger, nullable=False, primary_key=True)


class MachineA(Machine):
    system = relationship('SystemA')
   
    __table_args__ = {'schema': 'A'}


class MachineB(Machine):
    system = relationship('SystemB')
   
    __table_args__ = {'schema': 'B'}

到目前为止,这正在按预期工作,但是一旦我开始为各个架构添加带有外键的表,我就会遇到问题。

这是一个系统表的例子:

class System(Base):
    __tablename__ = 'system'
    __abstract__ = True

    id = Column('id', BigInteger, primary_key=True, autoincrement=True)
    machine_id = Column(BigInteger, ForeignKey('machines.id'), nullable=False)
    ts = Column('ts', TIMESTAMP(timezone=True), nullable=False)
    value = Column('value', JSONB())

    __table_args__ = (UniqueConstraint('machine_id', ts, value),
                      Index('system_machine_id_index', machine_id),
                      Index('system_ts_index', ts))


class SystemA(System):

    __table_args__ = (*System.__table_args__,
                      {'schema': 'A'})


class SystemB(System):

    __table_args__ = (*System.__table_args__,
                      {'schema': 'B'})

创建表时出现以下错误:

sqlalchemy.exc.InvalidRequestError: Columns with foreign keys to other columns must be declared as @declared_attr callables on declarative mixin classes.
  For dataclass field() objects, use a lambda:.

我尝试使用:

@declared_attr
def machine_id(cls):
    return Column(BigInteger, ForeignKey('machines.id'), nullable=False)

这没有用。我错过了什么吗?谢谢!

【问题讨论】:

    标签: python postgresql oop sqlalchemy orm


    【解决方案1】:

    找到了解决办法。我必须将 machine_id 设为字符串:

    __table_args__ = (UniqueConstraint('machine_id', ts, value),
                          Index('system_machine_id_index', 'machine_id'),
                          Index('system_ts_index', ts))
    

    更重要的是,在 ForeignKey 调用中引用架构:

    @declared_attr
    def machine_id(cls):
        return Column(BigInteger, ForeignKey('A.machines.id'), nullable=False)
    

    在 __table_args__ 中指定模式对于 mixin 声明是不够的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-13
      • 2021-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多