我有两个模型,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()
时会引发关键错误。如果我在PDB中调用self.id
,则会得到一个值(1)。但是,如果我调用self.__dict__
,则只会得到一个InstanceState,没有任何属性。因此,它抛出一个keyError。但是有时,通过在PDB中调用self_dict和self。 dict ,我可以使字典实际出现并具有值-这是我不了解的部分。撇开它,程序在这里失败,因为给定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
答案 0 :(得分:0)
如果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)