SQLAlchemy:如何以编程方式创建关系

时间:2017-09-05 13:50:42

标签: python sqlalchemy

我想动态地在两个表之间创建1:n关系。我的数据库模型是通过SQLAlchemy映射的,但由于我的应用程序的一些特殊功能,我不能使用默认的声明方式。

E.g。

class Foo(Base):
    id = Column(Integer, autoincrement=True, primary_key=True)
    flag = Column(Boolean)

class Bar(Base):
    id = Column(Integer, autoincrement=True, primary_key=True)
    foo_id = Column(Integer, ForeignKey('foo.id'))
    # declarative version:
    # foo = relationship(Foo)

所以我想在定义了 Bar之后将名为“foo”的关系添加到映射的类“Bar”,并且SQLAlchemy完成了定义映射器等的工作。

更新2017-09-05:为什么这对我来说是必要的? (我以为我可以省略这个,因为我认为它主要会分​​散实际问题而无法解决,但因为有关于它的评论......)

首先,我没有一个数据库,但数百/数千。旧数据库中的数据不得以任何方式进行更改,但我希望使用单个源代码来访问旧数据(即使数据结构和计算规则发生显着变化)。

目前我们使用多个模型定义。后来的定义扩展/修改以前的定义。我们经常动态地操纵SQLAlchemy模型。我们尽量不在映射类中使用代码,因为我们认为在多次更改表之后确保代码的正确性会更加困难(代码必须在每个中间步骤中工作)。

在许多情况下,我们在模型X中最初定义之后,在模型X中以编程方式扩展表(映射类)。将列添加到现有SQLAlchemy ORM类是可管理的。现在我们在现有表中添加一个新的引用列,relationship()提供了一个更好的Python API。

1 个答案:

答案 0 :(得分:0)

好吧,我上面的问题再次成为SQLAlchemy的超级权力(以及我有限的理解)的一个很好的例子:

 Bar.__mapper__.add_property('foo', relationship('Foo'))

可能我最初无法开始工作,因为我周围的一些代码混合了添加关系和列。声明列也有一个重要区别:

Column('foo', Integer)

对于列,第一个参数可以是列名,但不能将其用于关系。 relationship('foo', 'Foo')将异常传递给.add_property()时会触发异常。