如何使用一个 SQLAlchemy 模型保存到两个表

Posted

技术标签:

【中文标题】如何使用一个 SQLAlchemy 模型保存到两个表【英文标题】:How to save to two tables using one SQLAlchemy model 【发布时间】:2010-05-19 11:07:44 【问题描述】:

我有一个链接到 mysql 的 SQLAlchemy ORM 类,它非常适合将我需要的数据保存到基础表中。不过,我还想将相同的数据保存到 second 存档表中。

这里有一些伪代码来尝试解释我的意思

my_data = Data() #An ORM Class
my_data.name = "foo"

#This saves just to the 'data' table
session.add(my_data)

#This will save it to the identical 'backup_data' table
my_data_archive = my_data
my_data_archive.__tablename__ = 'backup_data'
session.add(my_data_archive)

#And commits them both
session.commit()

请注意,我对将类映射到 JOIN 不感兴趣,例如:http://www.sqlalchemy.org/docs/05/mappers.html#mapping-a-class-against-multiple-tables

【问题讨论】:

我很难想象这个复制品会给你带来什么。你想达到什么目的?在应用层保持简单的情况下,让 DBM 代表您执行此类冗余可能更符合 MySQL 的操作。 对不起,让我澄清一下:数据表将在稍后对其进行处理和汇总,但是我们仍然需要所有原始数据用于审计目的。因此,未更改的数据也应保存在 data_backup 表中。 (这些是示例名称) 另外,我认为像你建议的那样将逻辑放入数据库会损害我的应用程序。 【参考方案1】:

我在下面列出了一些选项。如果您不需要处理模型中的这些对象,我会选择 DB 触发器。

使用数据库触发器为您完成这项工作 创建一个SessionExtension,它将创建并添加到会话复制对象(通常在 before_flush 上)。 Edit-1:你可以把SA的versioning example作为基础;这段代码做得比你需要的还要多。 请参阅SA Versioning example,它不仅会为您提供对象的副本,还会为您提供整个版本历史记录,这可能是您想要的 请参阅Reverse mapping from a table to a model in SQLAlchemy 问题,blogpost 中描述了建议的解决方案。

【讨论】:

非常感谢您的帮助,但即使在阅读了您提供给我的资源后,我仍不确定如何继续。您能否给我一个小例子,说明如何非常简单地将单个模型保存到两个数据库表中?越简单越好。 触发器当然很简单,但这意味着将逻辑放入数据库中,对吗?我不确定这是最好的方法... 视情况而定。 logic 是什么?这真的是您的business 要求的一部分(模型可以反映和实现)还是non-functional 要求?很可能是后者,triggers 将以更简单且不易出错的方式处理这项工作。示例:您确定只通过model 更新您的数据吗?因为如果没有,那么出于审计原因,您将无法记录更改;但触发器会。我想说的是:您是正确目的的正确工具。你可以在 SA 中做到这一点,但相信我——你需要更多的经验。在 SA 中进行。【参考方案2】:

创建 2 个相同的模型:一个映射到主表,另一个映射到存档表。使用重新定义的方法after_insert() 创建一个MapperExtension(根据您的要求,您可能还需要after_update()after_delete())。此方法应将数据从主模型复制到存档并将其添加到会话中。有一些技巧可以自动复制所有列和多对多关系。

请注意,您必须 flush() session 两次来存储这两个对象,因为工作单元是在映射器扩展将新对象添加到会话之前计算的。你可以重新定义Session.flush() 来解决这个问题。刷新对象时还会分配自动递增的字段,因此如果您也需要它们,则必须延迟复制。

这是一种被证明可行的可能方案。我想知道是否有更好的方法。

【讨论】:

以上是关于如何使用一个 SQLAlchemy 模型保存到两个表的主要内容,如果未能解决你的问题,请参考以下文章

挂钩到 sqlalchemy 模型

Python/SQLAlchemy:如何将巨大的红移表保存到 CSV?

在 flask-sqlalchemy 中使用具有相同模型的多个数据库

如何在 SQLAlchemy 模型中使用 SQLAlchemy Utils

SQLAlchemy模型中的进程字段(使用flask_sqlalchemy)

SQLAlchemy Flask 过滤器查询以组合来自两个模型的结果