12

SQLAlchemy-0.7.8 を使用して Pyramid アプリを作成しています。私は64ビットのPython3.2を使用しています。

問題は、次の関数がデータベースに何もコミットしないのはなぜですか?

def create_card(sText,sCard):
    """
    create a wildcard instance if all is well (ie,sCard match in sText)
    return 
        oCard, dCard
    otherwise return False,False
    """
    oMatch = re.search(sCard,sText)
    if oMatch:
        oCard = WildCard()
        #set up some stuff about the WildCard

        DBSession.add(oCard)
        DBSession.flush()
        dCard = {
                    'id'            : oCard.id,
                    'span'          : oMatch.span(),
                    'card'          : oCard.card_string,
                            }
        return oCard,dCard
    return False,False  

別のスクリプトから DBSession をインポートします。次のように定義されます。

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))

背景情報は次のとおりです。

私が作成しているアプリは、正規表現を使用して HTML の大きなブロックを特徴付けるために使用するものです。アプリが動かなくなり、テキストの一部にワイルドカードの一致があるはずだと判断した場合、ユーザーには入力する小さなフォームが表示されます。フォームがコミットされると、create_card が呼び出されます。ワイルドカードが文字列と一致すると、WildCard インスタンスが作成されます。

WildCard クラスは特別なものではなく、文字列といくつかの整数を格納するだけです。dCard を出力すると、ワイルドカードの ID が整数であるため、正常にコミットされたように見えます。データベース セッションでフラッシュを呼び出さない場合、dCard['id'] は None です。

id フィールドは次のようになります。

id = Column(Integer,Sequence('wild_seq'), primary_key=True)

add および flush 行により、次のコンソール出力が生成されます。

2012-09-16 12:30:34,845 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] INSERT INTO wildcard_wildcards (card_string, range_id, brand_id, category_id, group_cat_map_id, heading_group_id, heading_to_grp_map_id, heading_id, value_map_id, igneore_match) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2012-09-16 12:30:34,845 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] ('sCard contents', None, None, None, None, None, None, None, None, 0)

したがって、この時点まで、すべてが期待どおりに動作しています。

ここに問題があります。WildCard インスタンスはデータベースにコミットされているように見え、例外は発生しませんが、データベースを直接調べると、変更が行われていないことがわかります。

flush() を commit() に置き換えると、次の例外が発生します。

AssertionError: Transaction must be committed using the transaction manager
4

1 に答える 1

25

トランザクションをコミットする必要があります。

これは明示的に行うことができます (呼び出すDBSession.commit()か、pyramid_tmミドルウェアを使用します。ミドルウェアは、応答が成功すると (2xx HTTP 応答で) トランザクションを自動的にコミットします)。

ZopeTransactionExtension後者は、セッション メーカーで拡張機能を使用する場合にのみ、SQLAlchemy のトランザクションをコミットします。

from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))

を既に使用していて、ZopeTransactionExtensionトランザクションを明示的にコミットしたい場合は、transactionパッケージを使用する必要があります: import transaction

transaction.commit()
于 2012-09-16T10:36:48.503 に答える