【发布时间】:2017-03-10 19:13:57
【问题描述】:
我有以下符号。警报可以有状态更改并且只有一个。 状态更改只能有一个警报。状态变化可能有一个原因,也可能是许多状态变化 我尝试了以下架构
class Alert(BaseDb):
__tablename__ = 'alerts'
__table_args__ = (
PrimaryKeyConstraint('id', name='pk_alerts'),
)
id = Column(Integer)
alert_text = Column(Text)
class AlertStateChange(BaseDb):
__tablename__ = 'alert_state_change'
__table_args__ = (
PrimaryKeyConstraint('id', name='pk_alert_state_change'),
ForeignKeyConstraint(
['reason_id'],
['reasons.id'],
name='fk_alert_status_change_reason_id__reasons'
),
ForeignKeyConstraint(
['alert_id'],
['alerts.id'],
name='fk_alert_status_change_alert_id__alert'
),
)
id = Column(Integer)
reason_id = Column(Integer)
alert_id = Column(Integer)
reason = relationship('Reason', backref='status')
alert = relationship('Alert',
backref=backref('status', uselist=False))
status = Column(Text)
但是 sqlalchemy 允许我为相同的警报(相同的 alert_id)添加到 AlertStateChange 对象。它通常使用新的 id 提交。将两个 AlertStatusChange 对象放在数据库中的同一警报中尝试以下操作后
alert.status
给我以下警告
SAWarning: Multiple rows returned with uselist=False for lazily-loaded attribute 'Alert.status' % self.parent_property)
并且返回的对象是添加的第一个 AlertStateChange 对象。第二个在数据库中但被忽略了。不应该引发异常吗?这不是真正的 OneToOne 关系。我应该将 alert_id 添加为主键或唯一值对吗?
【问题讨论】:
-
你是正确的,你应该在数据库级别强制执行一对一的方面,或者使用警报 id 作为主键/外键,或者对其具有唯一约束,如果你想确定。
-
请注意,SQLA 关系是一个 ORM 概念,它只是映射到数据库中的模式,或者这就是我从docs.sqlalchemy.org/en/latest/orm/tutorial.html 中理解的方式
标签: python sqlalchemy one-to-one