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にターゲットを追加することに依存してSessionいる場合、リクエストコンテキストに追加されたユーザーなどのオブジェクトが確実に処理されるようにするにはどうすればよいですか?

私がその仕事をすることを可能にしたことの1つは、で呼び出すことでしたがsessionmakerexpire_on_commit=Falseそれは私がやるべきことだとは思いません(素晴らしいSQLAドキュメントによると):

commit() のもう 1 つの動作は、デフォルトでは、コミットが完了した後に存在するすべてのインスタンスの状態が期限切れになることです。これは、次にインスタンスがアクセスされたときに、属性アクセスを介して、またはクエリ結果セットにインスタンスが存在することによって、最新の状態を受け取るようにするためです。この動作を無効にするには、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でnosetestを実行すると、同じエラーが発生しました。私の場合、 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 に答える