3

私のWSGIアプリケーションはSQLAlchemyを使用しています。リクエストの開始時にセッションを開始し、ダーティでリクエストの処理が正常に終了した場合はセッションをコミットし、それ以外の場合はロールバックします。したがって、Djangoの動作を実装する必要がありTransactionMiddlewareます。

したがって、WSGIミドルウェアを作成し、次のものを作成する必要があると思います。

  1. 前処理でDBセッションを作成して追加しますenviron
  2. エラーが発生しなかった場合は、からDBセッションを取得し、後処理environを呼び出します。commit()
  3. エラーが発生した場合は、からDBセッションを取得し、後処理environを呼び出します。rollback()

ステップ1は私には明らかです:

class DbSessionMiddleware:
def __init__(self, app):
    self.app = app

def __call__(self, environ, start_response):
    environ['db_session'] = create_session()
    return self.app(environ, start_response)

ステップ2と3-ではありません。後処理タスクのを見つけました:

class Caseless:
def __init__(self, app):
    self.app = app

def __call__(self, environ, start_response):
    for chunk in self.app(environ, start_response):
        yield chunk.lower()

コメントが含まれています:

この__call__関数はPythonジェネレーターであり、この種の「後処理」タスクで一般的であることに注意してください。

それがどのように機能し、どのように私の問題を同様に解決できるかを明確にしていただけませんか。

ありがとう、ボリス。

4

1 に答える 1

4

ステップ1では、SQLAlchemyスコープのセッションを使用します。

engine = create_engine(settings.DB_URL, echo=settings.DEBUG, client_encoding='utf8')
Base = declarative_base()

sm = sessionmaker(bind=engine)
get_session = scoped_session(sm)

これらは、get_session()呼び出しごとに同じスレッドローカルセッションを返します。

今のところ、ステップ2と3は次のとおりです。

class DbSessionMiddleware:
def __init__(self, app):
    self.app = app

def __call__(self, environ, start_response):
    try:
        db.get_session().begin_nested()
        return self.app(environ, start_response)
    except BaseException:
        db.get_session().rollback()
        raise
    finally:
        db.get_session().commit()

ご覧のとおり、セッションでネストされたトランザクションを開始して、ビューで既にコミットされているクエリもロールバックできるようにします。

于 2012-08-20T08:23:35.200 に答える