Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Sqlalchemy真的有一对一的关系吗_Python_Sqlalchemy_One To One - Fatal编程技术网

Python Sqlalchemy真的有一对一的关系吗

Python Sqlalchemy真的有一对一的关系吗,python,sqlalchemy,one-to-one,Python,Sqlalchemy,One To One,我有以下的权杖。警报可以有状态更改,但只能有一个。 状态更改只能有一个警报。状态更改可以有一个原因,也可以有多个原因 我尝试了以下模式 class Alert(BaseDb): __tablename__ = 'alerts' __table_args__ = ( PrimaryKeyConstraint('id', name='pk_alerts'), ) id = Column(Integer) alert_text = Column

我有以下的权杖。警报可以有状态更改,但只能有一个。 状态更改只能有一个警报。状态更改可以有一个原因,也可以有多个原因 我尝试了以下模式

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允许我为相同的警报(相同的警报id)添加AlertStateChange对象。它通常使用新id提交。将同一警报的两个AlertStatusChange对象放入数据库后,尝试以下操作

alert.status
给我以下警告

SAWarning: Multiple rows returned with uselist=False for lazily-loaded attribute 'Alert.status' % self.parent_property)
返回的对象是添加的第一个AlertStateChange对象。第二个在数据库中,但被忽略。难道不应该提出一个例外吗?这不是真正的一对一的关系。我可能应该将警报id添加为主键或唯一值,对吗?

执行以下操作:

  • 在关系上设置
    uselist=False
  • 在child
    unique=True中设置引用列
  • 您还可以在子对象上设置
    nullable=False
  • 您还可以添加到父自定义
    \uuuuu init\uuuu
    以实现严格的一对一
现在它可以工作了

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

如果您想确定的话,您应该在DB级别强制执行一对一方面,或者使用警报id作为主键/外键,或者对其使用唯一的约束。请注意,SQLA关系是一个ORM概念,它只是映射到DB中的模式,或者这就是我对它的理解