web-dev-qa-db-ja.com

dbオブジェクトを渡さずに、app.pyからFlaskモデルを分割するにはどうすればよいですか?

Flask-Migrate を使用して、その例を確認します。

_from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

db = SQLAlchemy(app)
migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))

if __name__ == '__main__':
    manager.run()
_

これは単純な遊びの例としてはうまく機能しますが、モデルが複数あるため、このスクリプトとアプリケーションコードを定義するスクリプトの両方でモデルを定義したくありません。したがって、2つの間で共有できるモデルファイルにそれらをプルしたいと思います。

Userクラスを_models.py_に配置し、そこからUserをインポートすることで、これを実行しようとしています。残念ながら、それは_NameError: name 'db' is not defined_をスローします。

私の質問は次のとおりです。

  • _models.py_でdb = SQLAlchemy(app)を使用する必要がありますか?使用する場合、これは移行スクリプトとflaskアプリケーション自体の両方で使用できますか?
  • _models.py_に入れることができない(または入れてはいけない)場合、dbを渡さずに、モデルを独自のファイルで利用するにはどうすればよいですか?
9
NewGuy

このような小さなアプリケーションをモジュールに分割するのは難しいです。作成する2つのモジュールが相互にインポートする必要があり、循環依存関係が作成される場合が多いためです。

アプリファクトリ関数とすべての拡張機能の初期化の遅延を使用して、より大きなアプリケーションを適切に構造化する方法を確認することをお勧めします。これを行うサンプルアプリケーションは、私の本で取り上げられている Flasky アプリです。

とはいえ、アプリケーションを2つの部分に分割することは可能ですが、インポートステートメントを配置する場所に注意する必要があります。以下の例では、dbインスタンスとUserモデルの作成をmodels.pyファイルに移動することにしました。

メインアプリケーションのモジュールは次のとおりです。

from flask import Flask
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'

from models import db  # <-- this needs to be placed after app is created
migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

if __name__ == '__main__':
    manager.run()

そしてここにmodels.pyがあります:

from __main__ import app
from flask.ext.sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))

ここで、メインモジュールはappを作成し、その後でのみmodels.pyをインポートします。 models.pyがメインモジュールからappをインポートしようとすると、すでに作成されています。移動した場合from models import db他のインポートを含むファイルの先頭に、このコードが壊れます。

17
Miguel

ここにアイデアがあります。クラスを個別の.pyファイルとして定義するパッケージmodelを作成できます。たとえば、user.pyにはUserクラスが含まれます。

__init__.pyファイルでは、db変数を定義できます。パッケージの外部でUserオブジェクトに直接アクセスできるように、from user import Userステートメントを含めることもできます。たとえば、import modelを使用してプログラム内の別の場所にmodelパッケージをインポートしてから、model.Userを使用してUserクラスを直接使用できます。

user.pydb変数を直接使用するには、from ..model import dbファイルで定義されたdb変数をインポートする__init__.pyを使用します。

0
aliasm2k