为什么我需要多对一关系的关系和外键?

时间:2019-02-14 16:21:08

标签: python sqlalchemy flask-sqlalchemy

在有关SQLAlchemy for Many to One关系的文档中,它显示以下示例:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer, ForeignKey('child.id'))
    child = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)

一个孩子的许多父母。然后,当我们创建一个Parent时,我们需要填充child_idchild,这似乎有点像多余的?这是强制性的,还是每件事的目的是什么?

child = Child()
Parent(child_id=child, child=child)

另外,在Flask-SQLAlchemy中,有this example for a simple relationship会在其中创建类似这样的帖子:

Post(title='Hello Python!', body='Python is pretty cool', category=py)

,不提供category_id。如果我复制该场景,则category_id的值为None

出于创建Parent(child=child)之类的新对象的目的,添加foreign_keys=[child_id]是否足够?还是有进一步的含义?

1 个答案:

答案 0 :(得分:3)

这不是强制性的;您无需同时填充两者。将外键设置为相关实例可能是一个错误,等待其自身显现。您唯一需要做的就是

child = Child()
parent = Parent(child=child)

parent.child_id之后是None,但它们代表了ORM的对象部分。 parent.child是对创建的child的引用。除了它们的Python对象ID外,它们还没有持久化到数据库中并且没有身份。仅当将它们添加到Session并将刷新内容刷新到数据库时,由于它们使用生成的代理密钥,它们才会收到标识。这是从对象世界到关系世界的映射发生的地方。 SQLAlchemy自动填充parent.child_id,以便它们的关系也记录在数据库中(请注意,这不是关系模型中的“关系”的意思)。

回到示例,添加一些打印有助于跟踪发生的情况和时间:

child = Child()
parent = Parent(child=child)
print(parent.child_id)  # None
session.add(parent)
session.flush()  # Send changes held in session to DB
print(parent.child_id)  # The ID assigned to child

您还可以扭转这种情况:您可能具有现有Child的ID,但没有实际的对象。在这种情况下,您只需自己分配child_id

因此,为了回答标题:您不需要ORM relationship来拥有数据库外键关系,但是您可以使用它来将数据库关系映射到对象世界。