这似乎很简单,但我似乎无法弄清楚如何;
我的项目中有一个存储金融交易的交易日志表。在大多数情况下,我必须连续编写一些这样的事务,它们共享很多属性。
所以我想做的是实例化一个Transactionlog对象,填写公共属性,然后继续将这个原始对象的副本添加到会话中。
我当前的代码是这样的(简化,它是更大的类方法的一部分):
t = Transactionlog()
t.tlog_newData = origin
t.tlog_ppl_id = self._contract.member.ppl_id
t.tlog_datetime = period.period_start
t.tlog_shift_datetime = period.period_end
t.tlog_artc_id = revenue_article_id
t.tlog_club_id = self._contract.member.ppl_club_id
t.tlog_ppl_mshp_id = self._contract.ppl_mshp_id
periodlabel = "{0} to {1}".format(period.period_start, period.period_end)
# linked periodical articles AB
for linkedarticle in self._contract.linkedarticles:
if linkedarticle.pmar_periodical:
if linkedarticle.pmar_free:
t.price = 0
else:
t.price = linkedarticle.article.artc_price
t.tlog_artc_id = linkedarticle.artc_id
t.tlog_comment = "{0}: {1}".format(periodlabel, linkedarticle.article.artc_description)
t.tlog_evtt_id = 'ab'
t.tlog_code = 'member_linked_article'
db_session.add(t)
# counterbook SIS
t2 = t
t2.tlog_evtt_id = 'sis'
t2.price = t.price * -1
t2.link(t)
db_session.add(t2)
t.tlog_code = None
db_session.commit()
你看到的是初始对象t的实例化。在链接文章下,我循环阅读了一堆文章,并(尝试)为每篇文章预订一个新的交易日志行,类型为AB。每个预订还有一个柜台预订SIS。
在数据库中我看到三个记录出现,但都具有相同的属性,它们都有tlog_evtt_id'sis'并且都具有价格-1。因此,它们似乎都获得了最近设置的属性。
我认为添加到SQLAlchemy会话会生成一个包含当前数据的INSERT,然后编辑现有对象并再次添加它将生成带有新数据的第二个INSERT。
简而言之,SQLAlchemy将现有对象的副本插入数据库的方式是什么?
答案 0 :(得分:1)
根据this answer,您需要一个复制构造函数:
class Transactionlog(Base):
...
@classmethod
def copy(cls, t):
t_new = cls()
t_new.tlog_newData = t.tlog_newData
...
您可以使用的另一个想法是functools.partial的帮助。我的示例假设您具有默认的SQLAlchemy构造函数:
data = {'tlog_newData': origin,
'tlog_ppl_id': self._contract.member.ppl_id,
...
}
make_log = functools.partial(Transactionlog, **data)
# linked periodical articles AB
for linkedarticle in self._contract.linkedarticles:
if linkedarticle.pmar_periodical:
t = make_log()
...
我会说这实际上是 clean 方式,因为它确实为您要添加的每个对象创建了一个新实例 - 这正是您想要的。是的,有开销,但是稍后从数据库中检索这些对象时也会产生开销:这是使用ORM的代价。