4

Flask と MongoDB (そしておそらく ODM として Ming) を使用して、Python で webapp を作成する予定です。問題は、モデルとコントローラーを十分に分離したいということです。その理由の 1 つは、別個のコンポーネントで単純な単体テストを実行できるようにするためです。

ここに私の問題があります。リクエストのライフサイクルのある時点で、MongoDB に接続する必要があります。各リクエストには個別の接続があります。Flask は、リクエストに対してグローバルな変数を含むことができるスレッド ローカル オブジェクトを提供します。これは、mongo 接続を配置するのに適しているようです。ただし、これにより、データ層と Flask の間に強い依存関係が生じ、それらを個別にテストまたは実行することが非常に困難になります。

したがって、私の質問は、これに対するエレガントな解決策があるかどうかです。私は自分でいくつかのオプションを考え出しましたが、それらはエレガントとはほど遠いものです。

まず、接続オブジェクトをどこから取得するかを伝える関数をデータ モジュールに与えることができます。または、同様に、新しい接続を取得するために使用できる関数を渡します。

2 番目のオプションは、モジュールが MongoDB への接続を取得するために使用できるクラスを作成し、このクラスの 2 つのバージョンを作成することです。1 つは Flask のグローバル オブジェクトを使用し、もう 1 つは単純に MongoDB に接続します。

これらは両方とも、私には本当に堅牢でもエレガントでもないようです。これを改善する方法はありますか?

4

1 に答える 1

5

1 つのアプローチは、Python モジュール レベルのシングルトン パターンを利用することです。「conn」オブジェクトを持つモジュールを作成します (プレーンな PyMongo のみを使用)。

try:
    conn = Connection(max_pool_size=20)
except ConnectionFailure:
    app.logger.critical("Unable to connect to MongoDB")

次に、PyMongo コレクションのラッパーを作成します。

class Model(object):
    def __init__(self, table, db = app.config['DB_NAME']):
        self._table = table
        self._db = db

    def find_one(self, spec_or_id=None, *args, **kwargs):
        result = None
        try:
            result = conn[self._db][self._table].find_one(spec_or_id, *args, **kwargs)
        except InvalidName:
            app.logger.critical('invalid DB or Table name')
        finally:
            conn.end_request()

        return result

conn.end_request()これにより、接続がプールに戻り、各 find_one() でプールから接続が取得されます。心配する必要はありません。これらはスレッド セーフです。

これで、次のようなモデルを使用できます

result = Model(COLLECTION).find_one({user:'joe'})
于 2011-12-17T14:57:18.037 に答える