Python 3.x SqlAlchemy中表内的多对一关系

Python 3.x SqlAlchemy中表内的多对一关系,python-3.x,sqlalchemy,Python 3.x,Sqlalchemy,我正在尝试创建一个模型类文档,其中可选地包含指向同一类(表)的其他两个元素的两个指针 原始_id,它应该保存表的另一个成员的索引,该表是文档的原始版本(可以为空) first_id,它应该保存作为存储的“第一个”文档的表的另一个成员的索引(可以为空) 我把我的班级定义为 class Document(Base): __tablename__ = 'documents' id = Column(Integer, primary_key=True) name = Colu

我正在尝试创建一个模型类文档,其中可选地包含指向同一类(表)的其他两个元素的两个指针

  • 原始_id,它应该保存表的另一个成员的索引,该表是文档的原始版本(可以为空)
  • first_id,它应该保存作为存储的“第一个”文档的表的另一个成员的索引(可以为空)
我把我的班级定义为

class Document(Base):
    __tablename__ = 'documents'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    original_id = Column(Integer, ForeignKey('documents.id'))
    original = relationship('Document', foreign_keys= original_id)
    
    first_id = Column(Integer, ForeignKey('documents.id'))
    first = relationship('Document', foreign_keys= first_id)

    def __repr__(self):
        return f'{self.name} ({self.id})'
但当我测试它如下:

d1 = Document(name='Dee one')
d2 = Document(name='Dee two')
d1.original.append(d2) # d1 has for original document d2
class Person(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    father_id = Column(Integer, ForeignKey('persons.id'))
    father = relationship('Person', remote_side= id, foreign_keys=father_id)
                                                     ^^^^^^^^^^^^^^^^^^^^^^   
    mother_id = Column(Integer, ForeignKey('persons.id'))
    mother = relationship('Person', remote_side= id, foreign_keys=mother_id)
                                                     ^^^^^^^^^^^^^^^^^^^^^^
我对存储在哪一行(提交后)的ID的实现感到惊讶

我想让d1.id保留2(dee2的索引)

很明显我做错了什么,但我很难理解是什么。看来我的关系是多对一的,但方向不对


我使用的是SQLAlchemy 1.3.5

最初,我希望有一个包含2个指向其他节点的可空指针的类。为了让关系更清楚,让我们给班上的人打电话,联系父亲和母亲。每个人最多都有一个已知的父亲和一个已知的母亲

根据文档,我创建了一个

class Person(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    father_id = Column(Integer, ForeignKey('persons.id'))
    father = relationship('Person')
这样做时,父亲关系是1对多的,即一个人可以有多个父亲,而父亲只能是1个孩子的父亲。这并不是人们所期望的

接下来,我找到了一种方法,使之成为一对多的关系。输入
远程侧
参数:

class Person(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    father_id = Column(Integer, ForeignKey('persons.id'))
    father = relationship('Person', remote_side=id)
                                    ^^^^^^^^^^^^^^
现在,关系如预期的那样。然而,由于有多个链接(父亲和母亲),这再次失败。即,如果我将该类细化为:

class Person(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    father_id = Column(Integer, ForeignKey('persons.id'))
    father = relationship('Person', remote_side= id)
    
    mother_id = Column(Integer, ForeignKey('persons.id'))
    mother = relationship('Person', remote_side= id)
SQLAlchemy失败,出现“含糊不清的ForeignKeyError”。然后,解决方案是指定用于链接父亲和母亲的字段,如下所示:

d1 = Document(name='Dee one')
d2 = Document(name='Dee two')
d1.original.append(d2) # d1 has for original document d2
class Person(Base):
    __tablename__ = 'persons'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    
    father_id = Column(Integer, ForeignKey('persons.id'))
    father = relationship('Person', remote_side= id, foreign_keys=father_id)
                                                     ^^^^^^^^^^^^^^^^^^^^^^   
    mother_id = Column(Integer, ForeignKey('persons.id'))
    mother = relationship('Person', remote_side= id, foreign_keys=mother_id)
                                                     ^^^^^^^^^^^^^^^^^^^^^^
现在,这一切都如期而至

因此,在某种程度上,这是中提供的解决方案的扩展


非常感谢Gord Thomson的评论。

在一对多关系中,父对象的外键值存储在子对象中。请注意,原始的_id存储在d2中,但d1.original(正确)返回d2对象。是的,但我想要一个多对一的关系,在这种情况下无法确定如何执行此操作。一对多和多对一是同一回事。它们都涉及一个父对象和零个或多个子对象。父对象与子对象之间存在一对多关系,子对象与父对象之间存在多对一关系。在您的例子中,d1是子对象,d2是父对象。我已经找到了解决方案,但它只适用于一个链接/指针/关系。当有多个时,SQLAlchemy会抱怨。因此,我的示例使用了两个字段“原始”和“字段”。但我终于找到了解决办法。我会写下来的。非常感谢你的评论。