1

我有一个与这个问题非常相似的问题但是,即使我尝试做类似的事情

...
from my_app.models import Session
user = Session.merge(user)
new_foo = models.Foo(user=user)
...

我基本上是从请求中获取用户模型对象并尝试创建一个Foo与用户有关系的新对象,但它失败了,DetachedInstanceError因为(我认为)event.listens我使用的稍后会出现不同的Session.

我的侦听器函数如下所示:

@event.listens_for(mapper, 'init')
def auto_add(target, args, kwargs):
    Session.add(target)

并且Session定义为:

Session = scoped_session(sessionmaker())

如果我依赖于event.listens将目标添加到 a Session,我如何确保处理添加到请求上下文中的像用户这样的对象?

让我完成这项工作的一件事是打电话sessionmakerexpire_on_commit=False但我不认为这是我应该做的(根据很棒的 SQLA 文档)它:

commit() 的另一个行为是,默认情况下,它会在提交完成后过期所有实例的状态>存在。这样,当实例下一次被访问时,无论是通过属性访问还是通过它们出现在查询结果集中,它们都会收到最新的状态。要禁用此行为,请使用 > 配置 sessionmaker expire_on_commit=False

我想拥有用户对象的最新状态。我有哪些选择可以在正确的地方照顾merge

实际的回溯(修剪了 Web 框架特定的行)如下所示:

  File "/Users/alfredo/python/my_app/my_app/models/users.py", line 31, in __repr__
    return '<User %r>' % self.username
  File "/Users/alfredo/.virtualenvs/my_app/lib/python2.7/site-packages/SQLAlchemy-0.8.0b2-py2.7-macosx-10.8-intel.egg/sqlalchemy/orm/attributes.py", line 251, in __get__
    return self.impl.get(instance_state(instance), dict_)
  File "/Users/alfredo/.virtualenvs/my_app/lib/python2.7/site-packages/SQLAlchemy-0.8.0b2-py2.7-macosx-10.8-intel.egg/sqlalchemy/orm/attributes.py", line 543, in get
    value = callable_(passive)
  File "/Users/alfredo/.virtualenvs/my_app/lib/python2.7/site-packages/SQLAlchemy-0.8.0b2-py2.7-macosx-10.8-intel.egg/sqlalchemy/orm/state.py", line 376, in __call__
    self.manager.deferred_scalar_loader(self, toload)
  File "/Users/alfredo/.virtualenvs/my_app/lib/python2.7/site-packages/SQLAlchemy-0.8.0b2-py2.7-macosx-10.8-intel.egg/sqlalchemy/orm/loading.py", line 554, in load_scalar_attributes
    (state_str(state)))
DetachedInstanceError: Instance <User at 0x10986d1d0> is not bound to a Session; attribute refresh operation cannot proceed

发生这种情况的实际方法是:

def post(self, *args, **kw):
    # Actually create one
    new_foo = Foo(user=request.context['user'], title=kw['title'], body=kw['body'])
    new_foo.flush()
    redirect('/pages/')

上面的问题是您看到我正在User从请求上下文中获取对象,并且发生在不同的情况下Session(或者至少,这是我假设正在发生的情况)。

编辑:似乎使用__repr__导致我出现问题,在请求期间的某个时刻,模型的字符串表示被调用,而我的模型的这一部分让我遇到了麻烦:

def __repr__(self):
    return '<User %r>' % self.username

如果我不实现该方法,那么我之前所拥有的一切都会按预期工作。我能做些什么来防止这种对 repr 的提高?

4

1 回答 1

0

当我用 sqlalchemy 运行鼻子测试时,我看到了同样的错误。就我而言, logging.getLogger('foo').debug('data %s', mydata) 犯了这个错误。'mydata' 是一个 sqlalchemy 映射实例,但尚未提交。我的解决方法是logging.getLogger('foo').debug('data %s', repr(mydata))

您可以更改__repr__以下方法以找出您的问题吗?

def __repr__(self):
    try:
        return '<User %r>' % self.username
    except:
        return 'I got it!'
于 2013-01-31T12:51:04.387 回答