如何在Flask Sqlalchemy中分离主从(DB读/写)

2024-09-27 07:28:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过Flask Sqlalchemy分离读写DB操作。我使用binds连接到mysql数据库。我想在Master中执行写操作,并从slaves读取。似乎没有一种内置的方法来处理这个问题。在

我是python新手,我很惊讶这样一个非常需要的功能还没有预先内置到flask sqlalchemy中。感谢任何帮助。谢谢


Tags: 方法功能master数据库flaskdbsqlalchemymysql
2条回答

虽然没有官方支持,但是您可以定制Flask SQLalchemy会话来使用主从连接

from functools import partial

from sqlalchemy import orm
from flask import current_app
from flask_sqlalchemy import SQLAlchemy, get_state


class RoutingSession(orm.Session):
    def __init__(self, db, autocommit=False, autoflush=True, **options):
        self.app = db.get_app()
        self.db = db
        self._bind_name = None
        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._bind_name:
            return state.db.get_engine(self.app, bind=self._bind_name)
        else:
            # if no bind is used connect to default
            return orm.Session.get_bind(self, mapper, clause)

    def using_bind(self, name):
        bind_session = RoutingSession(self.db)
        vars(bind_session).update(vars(self))
        bind_session._bind_name = name
        return bind_session


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,当您想从slave中选择时,可以直接调用它,下面是示例:

在你的应用程序中:

^{pr2}$

从主控形状中选择

session.query(User).filter_by(id=1).first() 

从从属服务器选择

session.using_bind('slave').query(User).filter_by(id=1).first() 

相关问题 更多 >

    热门问题