私はオンラインで見つかったベストプラクティスとMiguel Grinbergの "Flask Web Development"ブックの組み合わせに従って設定されたFlaskアプリケーションを実行しています。フラスコと他のアプリケーションの間でsqlalchemyモデルを共有
Webアプリケーションではなく、Flaskアプリケーションと同じモデルにアクセスする必要がある2番目のPythonアプリケーションが必要になりました。同じモデルを再利用したかったので、両方のアプリケーションが共有コードの恩恵を受けることができます。
フラスコのsqlalchemy拡張(これまでFlaskアプリケーションを使用していたときに使用していた)の依存関係を削除しました。そしてそれを少し簡単なSQLalchemy Declarative extension described hereに置き換えました(Flask-SQLalchemy adds a few specific things to standard SQLAlchemy)
この例では、ルートにdatabase.pyファイルを作成しました。私たちの場合、Declarativeの拡張の例とは異なる2つのことがあります。すべてのモデルがdb_sessionではなくdb.sessionを使用し、コンフィグレーション値を持つ辞書をinitに渡すため、エンジンとセッションをクラスに入れます()、私は別の設定を使用して、Flaskと他のアプリケーションの両方からこのdatabase.pyを再利用できるようになりました。
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
class Database(object):
def __init__(self, cfg):
self.engine = create_engine(cfg['SQLALCHEMY_DATABASE_URI'], convert_unicode=True)
self.session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=self.engine))
class Model(object):
pass
Base = declarative_base()
ここで実際の問題が発生します。 Flaskは設定オプションを含む辞書的なオブジェクトを作成し、プロパティとしてapp-instanceに追加します。サイトのルートにあるinstance folder、config.py、および環境変数からロードします。私はFlaskから設定辞書を渡す必要があるので、FlaskにFIRSTをロードして設定を組み立て、その後にデータベースを初期化し、アプリケーションファイルのルートに(設定された)dbオブジェクトを置く必要があります。しかし、我々はApplication factory patternに従っているので、さまざまな状況(テスト、生産、開発)に異なる構成を使用することができます。
from flask import Flask
from database import Database
from flask.ext.mail import Mail
from flask_bcrypt import Bcrypt
from config import config
mail = Mail()
bcrypt = Bcrypt()
def create_app(config_name):
app = Flask(__name__, instance_relative_config=True)
if not config_name:
config_name = 'default'
app.config.from_object(config[config_name])
app.config.from_pyfile('config.py')
config[config_name].init_app(app)
db = Database(app.config)
mail.init_app(app)
bcrypt.init_app(app)
@app.teardown_appcontext
def shutdown_session(exception=None):
db.session.remove()
from main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
しかしデシベル(モデルからインポートすること。)それはどこだから、今、create_app()関数内である必要があります:これは私たちのapp/__init__.py
はこのような何か(簡体字)を探します意味
Flaskは設定を読み込みます。 create_app()関数の外でdbオブジェクトをインスタンス化すると、モデルからインポートできますが、設定されていません!
モデル例は次のようになり、そしてあなたが見ることができるように、それはアプリのルートに「デシベル」を期待する:
from . base_models import areas
from sqlalchemy.orm import relationship, backref
from ..utils.helper_functions import newid
from .. import db
class Areas(db.Model, areas):
"""Area model class.
"""
country = relationship("Countries", backref=backref('areas'))
def __init__(self, *args, **kwargs):
self.area_id = newid()
super(Areas, self).__init__(*args, **kwargs)
def __str__(self):
return u"{}".format(self.area_name).encode('utf8')
def __repr__(self):
return u"<Area: '{}'>".format(self.area_name).encode('utf8')
だから私の質問は、私がいることを、DBインスタンスを持つことができるか、です外部(Flaskまたは他のアプリのいずれか)で設定でき、アプリケーションファクトリパターンは引き続き使用できますか?
編集:コード例が間違っていた、それはfrom database import Database
に置き換えられましたフラスコSQLAlchemyのために輸入していました。混乱を招いて申し訳ありません。
db.session.remove'が不要である 'を呼び出して、実際に問題を引き起こす可能性がティアダウン機能で設定されているよう
@app.teardown_appcontext
は必要ありません。 – davidismteardown関数は、Flaskのドキュメントに従って、Declarativeメソッドを使用してnessecaryです。http://flask.pocoo.org/docs/0.10/patterns/sqlalchemy/ –
これはスコープ付きセッションなので、それは冗長です。しかし、それを指摘してくれてありがとう、私はそれらのドキュメントを修正する必要があります。 – davidism