5

Flask に python-social-auth を実装しようとしています。約 4 つのチュートリアルと完全な Flask-book を同時に解釈しようとしているときに、大量のねじれを解決しました。

現在、次のコードを使用して、python-social-auth がフラスコの sqlalchemy 環境で機能するために必要なテーブルを作成しています。

from social.apps.flask_app.default import models
models.PSABase.metadata.create_all(db.engine)

現在、彼らは明らかに、私の実際の db-object とは関係なく、何らかの形の独自の Base を使用しています。これにより、Flask-Migrate はこれらのテーブルを完全に見逃し、移行でそれらを削除します。もちろん、すべての削除からこれらの db-drop を削除することはできますが、ある時点で忘れ去られ、突然 OAuth とのつながりがなくなったものの 1 つであると想像できます。

python-social-auth Flask の例で提案されているように、このソリューションを manage.py-command syncdb の使用 (および変更) で使用できるようにしました。

Flask-Migrate の作成者である Miguel Grinberg は、私の問題に非常によく似ていると思われる問題にここで返信します。

スタックオーバーフローで見つけた最も近いものはthisでしたが、それは私にとって全体にあまり光を当てておらず、答えは受け入れられませんでした(そして、私はそれを機能させることができません、私は数回試しました)

参考までに、私のmanage.pyは次のとおりです。

#!/usr/bin/env python

from flask.ext.script import Server, Manager, Shell
from flask.ext.migrate import Migrate, MigrateCommand


from app import app, db

manager = Manager(app)
manager.add_command('runserver', Server())
manager.add_command('shell', Shell(make_context=lambda: {
    'app': app,
    'db_session': db.session
}))

migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)

@manager.command
def syncdb():
    from social.apps.flask_app.default import models
    models.PSABase.metadata.create_all(db.engine)
    db.create_all()

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

明確にするために、db init / migrate / upgrade コマンドは私のユーザー テーブル (および明らかに移行テーブル) のみを作成しますが、ソーシャル認証のものは作成しませんが、syncdb コマンドは python-social-auth テーブルに対して機能します。

これはFlask-Migrateでサポートされていないことをgithubの応答から理解していますが、PSABaseテーブルをいじって、Migrateに送信されたdbオブジェクトによってピックアップされるようにする方法があるかどうか疑問に思っています。

どんな提案でも大歓迎です。

(また、初めてのポスターです。最終的にここに投稿する前に、多くの調査を行い、かなりの数の解決策を試したと思います。SOのガイドラインで明らかな何かを見逃した場合は、躊躇しないでくださいプライベート メッセージでその点を指摘していただければ、喜んで対応します)

4

3 に答える 3

4

ここでミゲルからの有益な回答の後、調査する新しいキーワードがいくつか得られました。最終的に、非常に役立つAlembic bitbucket サイトなどへの参照が含まれている便利な github ページにたどり着きました。

最後に、Alembic 移行 env.py-file に対してこれを行いました。

from sqlalchemy import engine_from_config, pool, MetaData

[...]

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app
config.set_main_option('sqlalchemy.url',
                       current_app.config.get('SQLALCHEMY_DATABASE_URI'))

def combine_metadata(*args):
    m = MetaData()
    for metadata in args:
        for t in metadata.tables.values():
            t.tometadata(m)
    return m

from social.apps.flask_app.default import models

target_metadata = combine_metadata(
    current_app.extensions['migrate'].db.metadata,
    models.PSABase.metadata)

これは完全に完全に機能するようです。

于 2016-02-04T09:09:13.340 に答える
2

問題は、それぞれが異なる SQLAlchemy メタデータ オブジェクトを持つ 2 つのモデル セットがあることです。PSA のモデルは SQLAlchemy から直接生成されましたが、独自のモデルは Flask-SQLAlchemy を介して生成されました。

Flask-Migrate は、Flask-SQLAlchemy を介して定義されたモデルのみを認識します。指定したdbオブジェクトは、これらのモデルのメタデータしか認識していないため、Flask-SQLAlchemy をバイパスした他の PSA モデルについては何も認識していません。

そうです、最終結果は、移行を生成するたびに、Flask-Migrate/Alembic が db でこれらの PSA テーブルを見つけ、それらのモデルが表示されないため、それらを削除することを決定することです。

問題の最善の解決策は、特定のテーブルを無視するように Alembic を構成することだと思います。これには、移行ディレクトリに保存されているモジュールのinclude_object構成を使用できます。env.py基本的に、移行スクリプトの生成中に新しいエンティティに遭遇するたびに Alembic が呼び出す関数を作成します。この関数はFalse、問題のオブジェクトがこれらの PSA テーブルの 1 つである場合、およびTrueその他すべての場合に戻ります。

更新: あなたが書いた応答に含めた別のオプションは、2 つのメタデータ オブジェクトを 1 つにマージすることです。その後、アプリケーションと PSA のモデルが Alembic によって一緒に検査されます。

複数のメタデータ オブジェクトを 1 つにマージする手法に反対するものは何もありませんが、アプリケーションが自分のものではないモデルの移行を追跡することは良い考えではないと思います。多くの場合、Alembic は移行を正確にキャプチャできないため、適用する前に、生成されたスクリプトに小さな修正を加える必要がある場合があります。自分のモデルの場合、移行スクリプトに時々現れるこれらの不正確さを検出できますが、モデルが自分のものではない場合、それらに加えられた変更に十分に慣れていないため、見逃す可能性があると思いますAlembic で生成されたスクリプトをよく確認するためのモデル。

このため、私が提案したinclude_object構成を使用して、サード パーティ モデルを移行から除外することをお勧めします。これらのモデルは、代わりにサードパーティ プロジェクトの指示に従って移行する必要があります。

于 2016-02-04T02:47:19.400 に答える