【问题标题】:Multi Database with same table name in flask_sqlalchemyflask_sqlalchemy 中具有相同表名的多数据库
【发布时间】:2020-03-20 13:51:02
【问题描述】:

我有多个数据库,比如order_db1order_db2order_db3

但他们都有表order,但order_db1.order中的数据与order_db2.order不同,

order_db1.order

|编号 |数量|

| 1| 100|

order_db2.order

|编号 |数量|

| 1| 200|

flask_sqlalchemy如何访问多个同名数据库?

我试过这样,用SQLALCHEMY_BINDS

# -*- coding: utf-8 -*-
from flask import Flask

from flask_sqlalchemy import SQLAlchemy
import logging


class Application(Flask):
    def __init__(self, import_name):
        super(Application, self).__init__(import_name)

app = Application(__name__)
db = SQLAlchemy(app)
app.config['SQLALCHEMY_BINDS'] = {
'order_db1': 'mysql://%s:%s@%s/order_db1' % (mysql_user, quote_plus(mysql_pwd),mysql_host),
'order_db2': 'mysql://%s:%s@%s/order_db2' % (mysql_user, quote_plus(mysql_pwd),mysql_host),
}


class Order1(db.model):
    __bind_key__ = 'order_db1'
    __tablename__ = 'order'
    id = db.colum(db.Interger)
    amount = db.colum(db.Interger)

class Order2(db.model):
    __bind_key__ = 'order_db2'
    __tablename__ = 'order'
    id = db.colum(db.Interger)
    amount = db.colum(db.Interger)

q1=Order1.query.get(1)
q2=Order2.query.get(1)

它告诉我:

'sqlalchemy.exc.InvalidRequestError: 已经为此 MetaData 实例定义了表 'order'。指定 'extend_existing=True' 以重新定义现有 Table 对象上的选项和列。'

但是如果我添加__table_args = {'extend_existing': True}


class Order1(db.model):
    __bind_key__ = 'order_db1'
    __tablename__ = 'order'
    __table_args = {'extend_existing': True}

    id = db.colum(db.Interger)
    amount = db.colum(db.Interger)


class Order2(db.model):
    __bind_key__ = 'order_db2'
    __tablename__ = 'order'
    __table_args = {'extend_existing': True}

    id = db.colum(db.Interger)
    amount = db.colum(db.Interger)

q1=Order1.query.get(1)
q2=Order2.query.get(1)

q1中的数据与q2相同,表示id=1,amount=200

我想要这样:

q1:id=1,金额=100

q2:id=1,金额=200

【问题讨论】:

  • 您是否按照documentation 中的说明声明了绑定。如果是,请提供代码。
  • 是的,我声明了它并用代码更新了我的问题
  • 存在绑定和相同表名的已知问题。看到这个discussion 和这个可能的workaround

标签: sqlalchemy flask-sqlalchemy


【解决方案1】:

绑定和相同的表名存在已知问题。请参阅此discussion 和此可能的workaround

另一种解决方法是使用两个 Sqlalchemy 实例,这对于您的用例可能是可接受的,也可能是不可接受的。查看使用 SQLite 的单个文件示例。

import random
from flask import Flask, render_template_string
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_BINDS'] = {
    'order_db1': 'sqlite:///order_db1.sqlite',
    'order_db2': 'sqlite:///order_db2.sqlite',
}

db1 = SQLAlchemy(app)
db2 = SQLAlchemy(app)


class Order1(db1.Model):
    __bind_key__ = 'order_db1'
    __tablename__ = 'order'

    id = db1.Column(db1.Integer, primary_key=True)
    amount = db1.Column(db1.Integer)


class Order2(db2.Model):
    __bind_key__ = 'order_db2'
    __tablename__ = 'order'

    id = db2.Column(db2.Integer, primary_key=True)
    amount = db2.Column(db2.Integer)


_html_template = '''
        <p>Order 1 count:{{order_1_count}}</p>
        <p>Order 2 count:{{order_2_count}}</p>
    '''


@app.route('/')
def index():
    order_1_count = Order1.query.count()
    order_2_count = Order2.query.count()

    return render_template_string(_html_template, order_1_count=order_1_count, order_2_count=order_2_count)


@app.before_first_request
def build_sample_db():

    db1.drop_all()
    db2.drop_all()

    db1.create_all()
    db2.create_all()

    # Create 100 records in db1
    db1.session.add_all([Order1(amount=random.randint(0, 100)) for _ in enumerate(range(0, 100))])
    db1.session.commit()

    # Create 1000 records in db1
    db2.session.add_all([Order2(amount=random.randint(1000, 10000)) for _ in enumerate(range(0, 1000))])
    db2.session.commit()

    return app


if __name__ == '__main__':
    app.run()

【讨论】:

    猜你喜欢
    • 2018-05-24
    • 2012-01-06
    • 1970-01-01
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多