Flask の view で依存を排除したい

Flask を使ってアプリケーションを書いていてどうやってやるんだろうと思ったので、ちょっと試してみた。


Flask の view 関数内でロジックとなる部分を呼び出す場合 view 関数でインスタンスを生成する。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask

# ロジック部分のクラス
class Foo(object):
    def users(self):
        return 'Foo.users'


# ロジック部分のクラス                      
class Bar(object):    
    def users(self):  
        return 'Bar.users'


@app.route('/') 
def index():
    foo = Foo()
    users = foo.users()

    return dict(foo=users)


if __name__ == '__main__':
    app.debug = True
    app.run()

こんな感じ。
ある程度の規模や保守/運用の時に改修が入った際に Foo() を Bar() に差し替えたいというのがあったら直接書き換えないといけない。
要は外部から注入して views のなかはいじらなくて済むようにしたい。
# テストで差し替えたい場合は mock を使えばいいと思う


Pyramid はここら辺を Resource Factory という仕組みを使えばうまい事できるそう。
http://d.hatena.ne.jp/imagawa_yakata/20120117/1326601571


Flask でもおんなじような事をしたい。
Flask 0.9 から app_context というのが入った。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from functools import wraps
from flask import Flask, current_app

app = Flask(__name__)


class Foo(object):
    def users(self):
        return 'Foo.users'


class Bar(object):     
    def users(self):   
        return 'Bar.users'


with app.app_context():
    current_app.injections = {}


def inject(**injections):
    def decorator(f):  
        @wraps(f)      
        def decorated_function(*args, **kwargs):
            for k, v in injections.iteritems():
                current_app.containers[k] = v

            return f(*args, **kwargs)
        return decorated_function
    return decorator


@app.route('/')
@inject(foo=Foo, bar=Bar)
def foo():
    service = current_app.injections['foo']
    foo = service()

    service = current_app.injections['bar']
    bar = service()

    return dict(foo=foo.users(), bar=bar.users)


if __name__ == '__main__':
    app.debug = True
    app.run()

こんな感じ?
current_app をコンテナとして利用したらできた。


これが正しいやりかたかどうか自信ないので、こうした方が良いとかアドバイス欲しいです。