2

SQLAlchemy 0.5 と Python 2.6.6 を使用しています。

association_proxy の作成者内で参照されるオブジェクトを選択または作成したいと考えています。私の問題は、これにはセッションが必要ですが、作成者のコールバックでこれを取得する場所がわかりません。

アソシエーション プロキシの作成者の 1 つで、オブジェクトが属するセッションを使用するにはどうすればよいですか?

私が試したこと、うまくいかないこと

を見つけましsession.object_sessionたが、ORM オブジェクトの一部でない限り、コールバックにオブジェクトがありません。それが私のオブジェクトの一部である場合、呼び出し元はメソッドとして呼び出されません (最初の引数は、オブジェクトの参照ではなく、プロキシの値です):

class Event(ManagerBase):

    # If association_proxy calls this, 'self' is the key, not the
    # reference to the calling instance.
    def _field_find_or_create(self, key, val):
        session = session.object_session(self)
        field = session.query(Field).filter_by(name=key).first()
        if not field:
            field = Field(name=key)

        return EventFieldValue(field=field, value=val)

    fields = association_proxy("field_values", "value",
                               creator=_field_find_or_create)

オブジェクト自体を Creators 関数に渡すことはできますか? この場合、このオブジェクトで object_session を呼び出すことができます。

私のプロジェクトは複数のセッションを使用しているため、作成者の実行時に具体的なセッションを決定する必要があります。

4

2 に答える 2

1

必要なのは検証メソッドだと思います:

from sqlalchemy.orm import validates, object_session

class Event(ManagerBase):
   value = relationship(FieldValue)    
   fields = association_proxy("field_values", "value",
                              creator=lambda group: FieldValue(value=value))

   @validates("field_values") 
   def _validate_field_values(self, key, value): 
       session = object_session(self) 
       if session is not None: 
           v = value.value 
           with session.no_autoflush: 
               uvalue = session.query(FieldValue) \ 
                   .filter_by(name=a) \ 
                   .first() 
               if uvalue: 
                   session.expunge(value) 
                   return ugroup 
       return value

クレジットはhttps://groups.google.com/forum/#!topic/sqlalchemy/RMDI1SnGhd0に送られます。

于 2014-08-05T08:39:10.317 に答える
0

この問題はSQLAlchemy0.7でも発生します。少し異なる状況で同じ問題が発生しました。AssociationproxyはPython記述子であり、記述子はクラスレベルで動作するため、作成者関数にバインドされたメソッド(インスタンスレベルで動作する)への参照を与えることはできません。

私は次の解決策に到達しました:

  1. クリエーター関数内で、グローバルセッションメーカーから新しいセッションを作成し、オブジェクトをフェッチします
  2. フェッチしたオブジェクトをこの一時的なセッションからすぐに消去します
  3. セッションを閉じる
  4. オブジェクトを返す

私のコードは次のようになります:

def find_object(name):                                                                                                                                                                                    
    # Because we can't get a grip on the actual session we instead use a global
    # session for querying this instance.
    session = Session()
    obj = Model.query(session).filter_by(name=name).first()
    # We also have to dump the reference to that session, so the created object
    # can be used on other sessions.
    session.expunge(obj)
    # We don't need that session any more.
    session.close()
    return obj
于 2012-09-27T15:04:39.303 に答える