我正在尝试通过Flask Sqlalchemy分离读写DB操作。我正在使用绑定来连接到mysql数据库。我想在Master中执行写操作,从Slave中读取。似乎没有一种内置的方法来处理这个问题。
我是python的新手,并且很惊讶这样一个非常需要的功能并没有预先构建到flask-sqlalchemy中。任何帮助表示赞赏。感谢
答案 0 :(得分:0)
没有官方支持,但是您可以自定义Flask-SQLalchemy会话以使用主从连接
from flask_sqlalchemy import SQLAlchemy, get_state
import sqlalchemy.orm as orm
from functools import partial
from flask import current_app
class RoutingSession(orm.Session):
def __init__(self, db, autocommit=False, autoflush=False, **options):
self.app = db.get_app()
self.db = db
self._name = None
self._model_changes = {}
orm.Session.__init__(
self, autocommit=autocommit, autoflush=autoflush,
bind=db.engine,
binds=db.get_binds(self.app), **options)
def get_bind(self, mapper=None, clause=None):
try:
state = get_state(self.app)
except (AssertionError, AttributeError, TypeError) as err:
current_app.logger.info(
"cant get configuration. default bind. Error:" + err)
return orm.Session.get_bind(self, mapper, clause)
# If there are no binds configured, use default SQLALCHEMY_DATABASE_URI
if not state or not self.app.config['SQLALCHEMY_BINDS']:
return orm.Session.get_bind(self, mapper, clause)
# if want to user exact bind
if self._name:
return state.db.get_engine(self.app, bind=self._name)
else:
# if no bind is used connect to default
return orm.Session.get_bind(self, mapper, clause)
def using_bind(self, name):
s = RoutingSession(self.db)
vars(s).update(vars(self))
s._name = name
return s
class RouteSQLAlchemy(SQLAlchemy):
def __init__(self, *args, **kwargs):
SQLAlchemy.__init__(self, *args, **kwargs)
self.session.using_bind = lambda s: self.session().using_bind(s)
def create_scoped_session(self, options=None):
if options is None:
options = {}
scopefunc = options.pop('scopefunc', None)
return orm.scoped_session(
partial(RoutingSession, self, **options), scopefunc=scopefunc
)
默认会话将为master
,当您要从从属服务器中进行选择时,可以直接调用它,例如:
在您的应用中:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///master'
app.config['SQLALCHEMY_BINDS'] = {
'slave': 'postgresql:///slave'
}
db = RouteSQLAlchemy(app)
从主菜单中选择
session.query(User).filter_by(id=1).first()
从奴隶中选择
session.using_bind('slave').query(User).filter_by(id=1).first()
答案 1 :(得分:-2)