python - 如何从父实例创建子 SQL-Alchemy 实例?
问题描述
我有两个模型,Signal
和Trade
。我的Trade
对象从 继承其属性Signal
,因为几乎所有属性都是相同的,但是有一些关键功能和属性使其不同。我正在编写一个方法Signal
,as_trade()
我想Trade
从实例上的所有数据/属性创建一个实例,Signal
以便将其保存到数据库中。我正在使用 deepcopy - 这一直有效,但实际上我认为这不是正确/最佳的方法。是否有一种经过尝试/测试的方式来执行这样的操作?
class Signal(db.Model):
__tablename__ = 'signal'
id = db.Column(db.Integer, primary_key=True)
class_type = db.Column(db.String())
__mapper_args__ = {
'polymorphic_identity': 'signal',
'polymorphic_on': class_type,
}
# MAIN FIELDS
type = db.Column(db.String(20))
def as_trade(self):
signal_dict = self.__dict__
for key in ['id', 'user_id', '_sa_instance_state', 'class_type']:
signal_dict.pop(key)
trade = Trade(**signal_dict)
return trade
...
class Trade(Signal):
__tablename__ = 'trade'
id = db.Column(db.Integer, db.ForeignKey('signal.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'trade',
}
....
我应该补充一点,我在这里遇到的问题是,当as_trade()
被调用时,它会引发一个关键错误。如果我调用self.id
PDB,我会得到一个值 (1)。但是,如果我打电话,self.__dict__
我只会得到一个 InstanceState,没有任何属性。因此,它会抛出一个 keyError。但有时,通过调用 self_dict 和 self. dict而在 PDB 中,我可以让字典实际出现并具有值 - 这是我不明白的部分。不理会,程序在这里失败,因为它在给定 self 时抛出了 keyError。dict只给出InstanceState
对象。但是在 PDB 中四处寻找并调用 self. dict在此过程中领先一步允许完成 for 循环,因为字典出现时包含所有必需的属性...?
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x000002E694983B88>
}
更新:它表现时髦的原因是因为_sa_instance_state
从字典中弹出,状态正在发挥作用。如果我留_sa_instance_state
在字典对象中并将其传递给 Trade(),则会出现错误TypeError: '_sa_instance_state' is an invalid keyword argument for Trade
解决方案
如果Signal
类和Trade
类共享相同的数据库列,并且它们的唯一区别在于类上定义的方法,那么使用单表继承模型是有意义的。
如果您不定义表名,Flask-SQLAlchemy 会神奇地定义表名,因此您需要显式设置__tablename__
子类的属性None
以表明您打算使用单表结构。
然后,如果目标是将Signal
对象列的值复制到新Trade
对象,那么您可以遍历 的列,Signal.__table__
以便从中获取列的值Signal
并将它们写入 的新实例Trade
。
循环看起来像这样:
signal = db.session.query(Signal).one()
new_trade = Trade()
for col in Signal.__table__.c:
if col.key not in ("id", "type"):
setattr(new_trade, col.key, getattr(signal, col.key))
这是一个完整的工作示例:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///test.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
class Signal(db.Model):
__tablename__ = "signal"
id = db.Column(db.Integer, primary_key=True)
# MAIN FIELDS
type = db.Column(db.String(20))
col1 = db.Column(db.Integer)
col2 = db.Column(db.Integer)
__mapper_args__ = {"polymorphic_on": "type", "polymorphic_identity": "signal"}
class Trade(Signal):
__tablename__ = None
__mapper_args__ = {"polymorphic_identity": "trade"}
if __name__ == "__main__":
db.drop_all()
db.create_all()
db.session.add(Signal(col1=1, col2=2))
db.session.commit()
signal = db.session.query(Signal).one()
new_trade = Trade()
for col in Signal.__table__.c:
if col.key not in ("id", "type"):
setattr(new_trade, col.key, getattr(signal, col.key))
db.session.add(new_trade)
db.session.commit()
db.session.expire_all()
trade = db.session.query(Trade).first()
print(trade.col1, trade.col2)
推荐阅读
- java - AspectJ java 13 支持?
- html - CSS 网格间距不正确
- python - 对不同索引的 ndarray 分配是线程安全的吗?
- ios - 是否有任何代表在应用程序仅从后台被杀死时触发?
- amazon-web-services - AWS S3 - 减速:请降低您的请求率
- r - 跨数据框创建循环并基于分组发送电子邮件
- ios - iOS13 暗模式披露指示器:不可读
- python - 在一个 Python 会话中调查不同版本的 Python 包
- python - 通过pyodbc访问全局临时表
- python - 如何在 Python 中使用 lxml 从 html 中提取除 css 和 javascript 之外的所有文本?