我有以下几种语言。警报可以更改状态,只有一个。 状态更改只能有一个警报。状态变化可能有一个原因,也可能是因为maney状态发生变化 我尝试了以下架构
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允许我为同一个警报添加AlertStateChange对象(相同的alert_id)。它通常使用新的id进行提交。在db中为同一个警报放置两个AlertStatusChange对象后,尝试以下
alert.status
给了我以下警告
SAWarning: Multiple rows returned with uselist=False for lazily-loaded attribute 'Alert.status' % self.parent_property)
并返回的对象是添加的第一个AlertStateChange对象。第二个是在数据库中但被忽略了。不应该提出异常吗?这不是一个真正的OneToOne关系。我应该将alert_id添加为主键或唯一值是否正确?
答案 0 :(得分:2)
执行以下操作:
uselist=False
unique=True
nullable=False
__init__
以进行严格的一对一现在它会起作用。
class Parent(Base):
__tablename__ = 'parents'
id = Column(Integer, primary_key=True)
Child = relationship("Child", uselist=False, backref="Parent")
def __init__(self,**kwargs):
if 'Child' not in kwargs:
raise RuntimeError('Need value')
...
class Child(Base):
__tablename__ = 'childs'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parents.id'), unique=True)
Base.metadata.create_all(engine)
session = Session(bind=engine)
ch1 = Child(Parent=Parent())
session.add(ch1)
p1 = Parent(Child=Child())
session.add(p1)
session.commit()
for row in session.query(Parent):
print row.Child.id
for row in session.query(Child):
print row.Parent.id