在有关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_id
和child
,这似乎有点像多余的?这是强制性的,还是每件事的目的是什么?
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]
是否足够?还是有进一步的含义?
答案 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
来拥有数据库外键关系,但是您可以使用它来将数据库关系映射到对象世界。