How to separate Master Slave (DB read / writes) in Flask Sqlalchemy

2024/9/30 5:38:59

I'm trying to separate the Read and write DB operations via Flask Sqlalchemy. I'm using binds to connect to the mysql databases. I would want to perform the write operation in Master and Reads from slaves. There does not seem to be an in built way to handle this.

I'm new to python and was surprised that a much needed functionality like this is not pre-built into flask-sqlalchemy already. Any help is appreciated. Thanks

Answer

There is no official support, but you can customize Flask-SQLalchemy session to use master slave connects

from functools import partialfrom sqlalchemy import orm
from flask import current_app
from flask_sqlalchemy import SQLAlchemy, get_stateclass RoutingSession(orm.Session):def __init__(self, db, autocommit=False, autoflush=True, **options):self.app = db.get_app()self.db = dbself._bind_name = Noneorm.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_URIif not state or not self.app.config['SQLALCHEMY_BINDS']:return orm.Session.get_bind(self, mapper, clause)# if want to user exact bindif self._bind_name:return state.db.get_engine(self.app, bind=self._bind_name)else:# if no bind is used connect to defaultreturn 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 = namereturn bind_sessionclass 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,)

Than the default session will be master, when you want to select from slave you can call it directly, here the examples:

In your app:

from flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///master'
app.config['SQLALCHEMY_BINDS'] = {'slave': 'postgresql:///slave'
}db = RouteSQLAlchemy(app)

Select from master

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

Select from slave

session.using_bind('slave').query(User).filter_by(id=1).first() 
https://en.xdnf.cn/q/71118.html

Related Q&A

Why import class from another file will call __init__ function?

The structure of the project is:project - main.py - session.py - spider.pyThere is a class in session.py:import requestsclass Session:def __init__(self):self.session = requests.Session()print(Session c…

Flask: login session times out too soon

While editing a record, if there is a long wait of let say a few minutes (getting coffee) and then coming back to press the save (POST), I get redirected to the main page to login instead and the data …

Activate virtual environement and start jupyter notebook all in batch file

I created the following batch file: jupyter_nn.bat. Inside file I have:cd "C:\My_favorite_path" activate neuralnets jupyter notebookSo the goal is to activate conda virtual environment and s…

several contour plots in the same figures

I have several 3d functions. I would like two plot the contour plots of them in the same figure to see the difference between them. I expect to see some crossings between contours of two functions. Her…

how to detect all the rectangular boxes in the given image

I tried to detect all the rectangles in image using threshold, canny edge and applied contour detection but it was not able to detect all the rectangles. Finally, I thought of detect the same using hou…

Python Pandas Series failure datetime

I think that this has to be a failure of pandas, having a pandas Series (v.18.1 and 19 too), if I assign a date to the Series, the first time it is added as int (error), the second time it is added as …

Remove a dictionary key that has a certain value [duplicate]

This question already has answers here:Removing entries from a dictionary based on values(4 answers)Closed 10 years ago.I know dictionarys are not meant to be used this way, so there is no built in fun…

Get names of positional arguments from functions signature

Using Python 3.x, Im trying to get the name of all positional arguments from some function i.e: def foo(a, b, c=1):returnRight now Im doing this: from inspect import signature, _empty args =[x for x, p…

Emacs Python-mode syntax highlighting

I have GNU Emacs 23 (package emacs23) installed on an Ubuntu 10.04 desktop machine and package emacs23-nox installed on an Ubuntu 10.04 headless server (no X installed). Both installations have the sam…

programmatically edit tab order in pyqt4 python

I have a multiple textfield in my form. My problem is the tab order is wrong. Is there a way to edit tab order in code? Just like in QT Designer.thanks.