解決:
現在のところ、これを行う最善の方法は次のとおりです。
sqlalchemy を実装またはインポートするbase
from sqlalchemy.ext.declarative import declarative_base
base = declarative_base()
class Base(base):
__abstract__ = True
uid = Column(Integer, primary_key=True, autoincrement=True)
外部ベースを登録します。
from flask_sqlalchemy import SQLAlchemy
from model.base import Base
app = Flask(__name__)
db = SQLAlchemy(app, model_class=Base)
後世のためにアーカイブ:
これに対する答えを探すのに多くの時間を費やしました。これは、私が最初に質問したときよりもはるかに簡単になりましたが、まだ単純ではありません。
セキュリティを自分で行うことに決めた人には、flask を使用するが、flask-security のような不要な依存関係を採用しない一般的な設計パターンの次の優れた解説をお勧めします:
https://exploreflask.com/users.html
更新:
興味のある方のために、これに関連してしばらくの間パッチが作成されています。現時点ではまだリリースされていませんが、ここで進捗状況を確認できます:
https://github.com/mitsuhiko/flask-sqlalchemy/pull/250#issuecomment-77504337
更新:
上記のパッチからコードを取得し、SQLAlchemy オブジェクトのローカル オーバーライドを作成して、外部ベースを登録できるようにしました。金融庁が正式に追加するまでは、これが最善の選択肢だと思います。興味のある人のために、そのクラスのコードを次に示します。Flask-SqlAlchemy 2.2 で動作テスト済み
register_external_base でのパッチ適用:
import flask_sqlalchemy
'''Created by Isaac Martin 2017. Licensed insofar as it can be according to the standard terms of the MIT license: https://en.wikipedia.org/wiki/MIT_License. The author accepts no liability for consequences resulting from the use of this software. '''
class SQLAlchemy(flask_sqlalchemy.SQLAlchemy):
def __init__(self, app=None, use_native_unicode=True, session_options=None,
metadata=None, query_class=flask_sqlalchemy.BaseQuery, model_class=flask_sqlalchemy.Model):
self.use_native_unicode = use_native_unicode
self.Query = query_class
self.session = self.create_scoped_session(session_options)
self.Model = self.make_declarative_base(model_class, metadata)
self._engine_lock = flask_sqlalchemy.Lock()
self.app = app
flask_sqlalchemy._include_sqlalchemy(self, query_class)
self.external_bases = []
if app is not None:
self.init_app(app)
def get_tables_for_bind(self, bind=None):
"""Returns a list of all tables relevant for a bind."""
result = []
for Base in self.bases:
for table in flask_sqlalchemy.itervalues(Base.metadata.tables):
if table.info.get('bind_key') == bind:
result.append(table)
return result
def get_binds(self, app=None):
"""Returns a dictionary with a table->engine mapping.
This is suitable for use of sessionmaker(binds=db.get_binds(app)).
"""
app = self.get_app(app)
binds = [None] + list(app.config.get('SQLALCHEMY_BINDS') or ())
retval = {}
for bind in binds:
engine = self.get_engine(app, bind)
tables = self.get_tables_for_bind(bind)
retval.update(dict((table, engine) for table in tables))
return retval
@property
def bases(self):
return [self.Model] + self.external_bases
def register_base(self, Base):
"""Register an external raw SQLAlchemy declarative base.
Allows usage of the base with our session management and
adds convenience query property using self.Query by default."""
self.external_bases.append(Base)
for c in Base._decl_class_registry.values():
if isinstance(c, type):
if not hasattr(c, 'query') and not hasattr(c, 'query_class'):
c.query_class = self.Query
if not hasattr(c, 'query'):
c.query = flask_sqlalchemy._QueryProperty(self)
# for name in dir(c):
# attr = getattr(c, name)
# if type(attr) == orm.attributes.InstrumentedAttribute:
# if hasattr(attr.prop, 'query_class'):
# attr.prop.query_class = self.Query
# if hasattr(c , 'rel_dynamic'):
# c.rel_dynamic.prop.query_class = self.Query
次のように使用するには:
app = Flask(__name__)
db = SQLAlchemy(app)
db.register_base(base)