如何用一个SQLAlchemy模型保存到两个表中
我有一个使用SQLAlchemy的ORM类,它连接到MySQL数据库,能很好地把我需要的数据保存到基础表中。不过,我还想把相同的数据也保存到一个第二个归档表里。
下面是一些伪代码,试着解释一下我的意思:
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
2 个回答
1
创建两个一模一样的模型:一个对应主表,另一个对应归档表。然后创建一个叫做 MapperExtension
的东西,并重新定义一个方法 after_insert()
(根据你的需求,你可能还需要 after_update()
和 after_delete()
)。这个方法的作用是把主模型中的数据复制到归档中,并把它添加到会话里。有一些小技巧可以自动复制所有的列和多对多关系。
需要注意的是,你必须调用 flush()
两次来存储这两个对象,因为在映射器扩展把新对象添加到会话之前,工作单元的计算已经完成了。你可以重新定义 Session.flush()
来解决这个问题。另外,自增字段是在对象被刷新时分配的,所以如果你也需要这些字段,就得延迟复制。
这是一种经过验证的可行方案。我想知道有没有更好的方法。
3
下面我列出了一些选项。如果你不需要在你的模型中处理那些对象,我建议你使用数据库触发器。
- 使用数据库触发器来帮你完成这个工作。
- 创建一个SessionExtension,它会在会话中创建并添加对象的副本(通常是在before_flush之前)。编辑-1:你可以参考版本控制示例作为基础;这段代码做的事情比你需要的还要多。
- 查看SA版本控制示例,它不仅会给你对象的副本,还会提供完整的版本历史,这可能正是你想要的。
- 查看从表到模型的反向映射问题,里面描述了一个解决方案,详细信息可以在这篇博客中找到。