【问题标题】:SQLAlchemy: how to create a relationship programmaticallySQLAlchemy:如何以编程方式创建关系
【发布时间】:2018-02-13 20:25:57
【问题描述】:

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

例如

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)

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

2017-09-05 更新: 为什么这对我来说是必要的? (我想我可以省略这个,因为我认为它主要分散了要解决的实际问题的注意力,但因为有 cmets 关于它......)

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

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

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

【问题讨论】:

  • 这背后的原因是什么?您想在创建多重关系时像使用外部模型列表一样使用吗?
  • 只需在类中添加一个关系属性,尽管@krassowski 是对的:你为什么需要它?
  • @ilja-everilä:你能详细说明一下吗?我需要将关系定义与实际声明完全分离。基本上我想知道如何操作 SQLAlchemy 的内部结构,但我在(非常好的)文档中找不到正确的部分,我希望有人可以为我节省几个小时阅读 SQLAlchemy 源代码的时间...... :-)
  • 如果我理解正确的话,这里可以节省时间:"Attributes may be added to the class after its construction, and they will be added to the underlying Table and mapper() definitions as appropriate"。因此,“仅添加”是指您可以在定义映射类后简单地将新关系属性栓接到映射类。

标签: python sqlalchemy


【解决方案1】:

好吧,我上面的问题又是一个很好的例子,说明了 SQLAlchemy 的超能力(以及我有限的理解):

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

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

Column('foo', Integer)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2012-01-14
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多