如何使用一个 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 模型保存到两个表的主要内容,如果未能解决你的问题,请参考以下文章
Python/SQLAlchemy:如何将巨大的红移表保存到 CSV?
在 flask-sqlalchemy 中使用具有相同模型的多个数据库
如何在 SQLAlchemy 模型中使用 SQLAlchemy Utils