multiple/split class sqlalchemy 中的关联

multiple/split class associations in sqlalchemy

我定义了以下对象和关系。这实际上是一个非常简单的案例,我提供所有这些字段只是为了说明为什么我认为吸入和注射麻醉应该由两个不同的 classes 来定义。

class InhalationAnesthesia(Base):
    __tablename__ = "inhalation_anesthesias"
    id = Column(Integer, primary_key=True)
    anesthetic = Column(String)
    concentration = Column(Float)
    concentration_unit = Column(String)
    duration = Column(Float)
    duration_unit = Column(String)


class TwoStepInjectionAnesthesia(Base):
    __tablename__ = "twostep_injection_anesthesias"
    id = Column(Integer, primary_key=True)
    anesthetic = Column(String)
    solution_concentration = Column(Float)
    solution_concentration_unit = Column(String)
    primary_dose = Column(Float)
    primary_rate = Column(Float)
    primary_rate_unit = Column(String)
    secondary_rate = Column(Float)
    secondary_rate_unit = Column(String)

class Operation(Base):
    __tablename__ = "operations"
    id = Column(Integer, primary_key=True)
    anesthesia_id = Column(Integer, ForeignKey('inhalation_anesthesias.id'))
    anesthesia = relationship("InhalationAnesthesia", backref="used_in_operations")

但是,我想定义 Operation class 的麻醉属性,这样任何 Operation 对象都可以指向 TwoStepInjectionAnesthesia对象或 InhalationAnesthesia 对象。

我该怎么做?

我建议你使用继承。在 SqlAlchemy 文档 here and here

中有非常非常好的解释

我的建议是创建一个 Anesthesia class 并使 InhalationAnesthesiaTwoStepInjectionAnesthesia 都继承自它。您可以决定使用哪种类型的 table 继承:

  • 单一table继承
  • 具体table继承
  • 加入table继承

The most common forms of inheritance are single and joined table, while concrete inheritance presents more configurational challenges.


对于你的情况,我假设 加入 table 继承 是选举:

class Anesthesia(Base)
    __tablename__ = 'anesthesias'
    id = Column(Integer, primary_key=True)
    anesthetic = Column(String)
    # ...
    # every common field goes here
    # ...
    discriminator = Column('type', String(50))
    __mapper_args__ = {'polymorphic_on': discriminator}

discriminator 字段的用途:

... is to act as the discriminator, and stores a value which indicates the type of object represented within the row. The column may be of any datatype, though string and integer are the most common.

__mapper_args__polymorphic_on 键定义哪个字段用作鉴别器。 在子 classes(下)中,polymorphic_identity 键定义将存储在 class 实例的多态鉴别器列中的值。

class InhalationAnesthesia(Anesthesia):
    __tablename__ = 'inhalation_anesthesias'
    __mapper_args__ = {'polymorphic_identity': 'inhalation'}
    id = Column(Integer, ForeignKey('anesthesias.id'), primary_key=True)
    # ...
    # specific fields definition
    # ...


class TwoStepInjectionAnesthesia(Anesthesia):
    __tablename__ = 'twostep_injection_anesthesias'
    __mapper_args__ = {'polymorphic_identity': 'twostep_injection'}
    id = Column(Integer, ForeignKey('anesthesias.id'), primary_key=True)
    # ...
    # specific fields definition
    # ...

最后 Operation class 可能会引用具有典型关系的父 table Anesthesia

class Operation(Base):
    __tablename__ = 'operations'
    id = Column(Integer, primary_key=True)
    anesthesia_id = Column(Integer, ForeignKey('anesthesias.id'))
    anesthesia = relationship('Anesthesia', backref='used_in_operations')

希望这就是您要找的。