I have two tables sharing the same name but located in different databases:
class Lcn(db.Model):
__tablename__ = 'lcn'
class LcnRemote(db.Model):
__bind_key__ = 'remote'
__tablename__ = 'lcn'
It seems SQLAlchemy doesn't like that. It says:
sqlalchemy.exc.InvalidRequestError: Table 'lcn' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
Is there a way to solve this without having to rename one of my tables?
Use separate declarative base classes for different databases with the same name, to prevent sharing of SQLAlchemy metadata.
If you are using a Flask-SQLAlchemy version older than 3.0.0 you’ll have to create two flask_sqlalchemy.SQLAlchemy()
instances:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/database1.db'
app.config['SQLALCHEMY_BINDS'] = {'remote': 'sqlite:////tmp/database1.db'}
db1 = SQLAlchemy(app)
class Lcn(db1.Model):
__tablename__ = 'lcn'
db2 = SQLAlchemy(app)
class LcnRemote(db2.Model):
__bind_key__ = 'remote'
__tablename__ = 'lcn'
This is a limitation of Flask-SQLAlchemy < 3.0.0, it really should allow you to create declarative bases per bind. The way the SQLAlchemy()
class in older versions is designed limits it to just one such base; it proxies various SQLAlchemy metadata calls through the db.Model
class it generates at the start. By creating two instances of flask_sqlalchemy.SQLAlchemy()
you work around this issue.
Version 3.0.0 allows you to use separate bases per bind key and your classes work out of the box. See the documentation on using binds.