Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Sqlalchemy没有';t调用模型&x27;对象刷新时的s重建器_Python_Sqlalchemy_Flask Sqlalchemy - Fatal编程技术网

Python Sqlalchemy没有';t调用模型&x27;对象刷新时的s重建器

Python Sqlalchemy没有';t调用模型&x27;对象刷新时的s重建器,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,我有一个模型,它应该在初始化时转换一些字段。我曾尝试使用sqlalchemy.orm.recostructor,但遇到了模型自动刷新的问题(或理解错误) 这是我的模型的示例: from app import db from sqlalchemy.orm import reconstructor t_model = db.Table( 'models', db.metadata, dbc.Column('id', db.Integer, primary_key=True

我有一个模型,它应该在初始化时转换一些字段。我曾尝试使用
sqlalchemy.orm.recostructor
,但遇到了模型自动刷新的问题(或理解错误)

这是我的模型的示例:

from app import db
from sqlalchemy.orm import reconstructor

t_model = db.Table(
    'models', 
    db.metadata,
    dbc.Column('id', db.Integer, primary_key=True),
    dbc.Column('value', db.String)
)


class Model(db.Model):

  __table__ = t_order_data

  def __init__(self, value)
      self.value = value

  @reconstructor
  def init_on_load(self)
      """cast to None if value is empty string"""
      self.value = None if not self.value else self.value

  def run_db_function(self)
      try:
          result = db.session.execute(db.func.somefunc('some_param')).fetchone()
      except Exception:
          db.session.rollback()
          raise
      else:
          db.session.commit()
          return result
我的代码做什么:

model = Model.query.get(1)  # in table this row is id=1, value=''
它开始隐式事务并选择模型数据

model.value  # returns None -- OK
然后我执行函数

model.run_db_function()
它运行DB的例程,然后提交事务

然后,当我尝试访问
value
属性时,sqlalchemy开始新的隐式事务,在该事务中重新获取该模型

但是这个时间值不会被转换

model.value  # returns '' -- NOT OK
sqlalchqmy ORM的官方文档介绍了
重构器
装饰器:

将一个方法指定为“reconstructor”,这是一个类似于
\uuuu init\uuuu
的方法,在实例从数据库加载或以其他方式重建后,ORM将调用该方法

从这个描述中,我假设在重新获取后也应该调用
init\u on\u load
,但事实并非如此


这是错误还是设计行为?如果这是正常行为,我该如何处理呢?

引用官方文件:

是进入更大的“实例级”事件系统的快捷方式,可以使用事件API订阅这些事件-有关这些事件的完整API描述,请参阅

本质上,
重构器()
是实现以下目的的快捷方式:

通过
\uuuuu new\uuuuu
创建对象实例后,以及初始属性填充发生后,接收对象实例。 ... 这通常发生在基于传入结果行创建实例时,并且在该实例的生存期内只调用一次

当您启动或回滚时,默认情况是终止会话中找到的实例的所有ORM控制属性。这些实例本身仍然存在。当您重新蚀刻与会话中找到的实例匹配的行时,该行将被删除。例如:

In [2]: from sqlalchemy.events import event

In [3]: class Foo(Base):
   ...:     id = Column(Integer, primary_key=True, autoincrement=True)
   ...:     value = Column(Unicode)
   ...:     __tablename__ = 'foo'
   ...:     
添加事件侦听器,以便跟踪正在发生的事情

In [5]: @event.listens_for(Foo, 'load')
   ...: def foo_load(target, context):
   ...:     print('Foo load')
   ...:     

In [6]: @event.listens_for(Foo, 'refresh')
   ...: def foo_load(target, context, attrs):
   ...:     print('Foo refresh')
   ...:     

In [7]: session.add(Foo(value='test'))

In [8]: session.commit()
构建了Foo实例

In [9]: foo = session.query(Foo).first()
Foo load

In [10]: session.rollback()
在会话中找到的现已过期的实例将被刷新并返回

In [11]: foo2 = session.query(Foo).first()
Foo refresh
两个名称都绑定到同一个实例

In [12]: foo is foo2
Out[12]: True

In [13]: session.rollback()
对过期实例的属性访问只会导致刷新

In [14]: foo.value
Foo refresh
Out[14]: 'test'

非常感谢您的详细回复!显然,我必须深入研究文档