提供具有多个数据库的页面

时间:2013-03-21 18:16:17

标签: python database sqlalchemy flask

我拥有:多个相同的数据库和SQL-Alchemy设置。

我需要实现的目标:单个“Flask”功能能够查询所有数据库。所有其他功能只需要访问其中一个数据库。

数据库已经存在,我正在从中加载数据。

最初我只使用SQL-Alchemy抽象层,没有任何Flask模型。这就是代码的样子:

app = Flask(__name__)
app.config.from_object('myflaskapp.config.settings')
metadata = None

def connect_db():
    engine = create_engine(app.config['DATABASE_URI'])
    global metadata
    metadata = MetaData(bind=engine)
    return engine.connect()

@app.before_request
    def before_request():
    g.db = connect_db()

@app.after_request
    def after_request(response):
    close_connection()
    return response

在settings.py中声明为DATABASE_URI。我想无所谓,但底层数据库是一个Mysql服务器,DATABASE_URI看起来像:

DATABASE_URI = 'mysql://' + dbuser + ':' + dbpass + '@' + dbhost + '/' +dbname

上面的代码允许我写这样的东西:

myTable = Table('branch', metadata, autoload=True)
myBranch = select([myTable])

非常方便。除非我必须处理多个DB,否则这种方法可以正常工作。更确切地说,我想(在同一个函数中)显示属于具有完全相同结构的多个DB的数据。这意味着可以在任何数据库中成功运行相同的查询。在伪代码中:

@app.route('/summary')
def summary():
     ....
     allData = []
     for db in all_of_my_dbs:
         allData.append(db.query())
     ....
sendToTemplate(allData) 

这是可行的吗?它可行吗? 谢谢。

3 个答案:

答案 0 :(得分:0)

绝对是possible

尝试将类似内容添加到您的设置文件

SQLALCHEMY_BINDS = {
    'users':        'mysqldb://localhost/users',
    'appmeta':      'sqlite:////path/to/appmeta.db'
}

修改

所以这是一个工作的复制/粘贴示例

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.debug = True

databases = {
    'sqlite1': 'sqlite:///sqlite1.db',
    'sqlite2': 'sqlite:///sqlite2.db'
}
app.config['SQLALCHEMY_BINDS'] = databases
db = SQLAlchemy(app)

class Thing(db.Model):
    __tablename__ = "sqlite1"
    thing_id = db.Column(db.Integer, primary_key=True)
    thing_val = db.Column(db.String(40))

    def __init__(self, thing_val):
        self.thing_val = thing_val

class Thing2(db.Model):
    __tablename__ = "sqlite2"
    thing_id = db.Column(db.Integer, primary_key=True)
    thing_val = db.Column(db.String(40))

    def __init__(self, thing_val):
        self.thing_val = thing_val


if __name__ == "__main__":

    db.create_all()
    t1 = Thing("test1")
    t2 = Thing2("test2")

    db.session.add(t1)
    db.session.add(t2)
    db.session.commit()

    t1 = Thing.query.filter_by(thing_id=1).first()
    t2 = Thing2.query.filter_by(thing_id=1).first()

    print t1.thing_val
    print t2.thing_val

答案 1 :(得分:0)

首先,我想谈谈我自己的情况。这两个表具有相同的名称,相同的DDL但属于不同的模式/数据库。

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)

databases = {
    'sqlite1': 'sqlite:///sqlite1.db',
    'sqlite2': 'sqlite:///sqlite2.db'
}

app.config['SQLALCHEMY_BINDS'] = databases
db = SQLAlchemy(app)

class Thing(db.Model):
    __tablename__ = "mytable"
    __bind_key__ = 'sqlite1'
    thing_id = db.Column(db.Integer, primary_key=True)
    thing_val = db.Column(db.String(40))

    def __init__(self, thing_val):
        self.thing_val = thing_val


if __name__ == "__main__":

    t1 = Thing.query.filter_by(thing_id=1).first()
    print t1.name

当我在第一个类定义之后添加第二个名为Thing2的类时,一切都会中断。即:

class Thing(db.Model):
    __tablename__ = "mytable"
    __bind_key__ = 'sqlite1'
    thing_id = db.Column(db.Integer, primary_key=True)
    thing_val = db.Column(db.String(40))

    def __init__(self, thing_val):
        self.thing_val = thing_val


class Thing2(db.Model):
    __tablename__ = "mytable"
    __bind_key__ = 'sqlite2'
    thing_id = db.Column(db.Integer, primary_key=True)
    thing_val = db.Column(db.String(40))

    def __init__(self, thing_val):
        self.thing_val = thing_val

上面的代码打破了这个错误:

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

因此框架似乎无法区分它们中的两个。

答案 2 :(得分:0)

显然这个问题存在一个错误 - https://github.com/mitsuhiko/flask-sqlalchemy/pull/222所以问题是绑定键必须是唯一的,并且只能用于一个类(至少目前为止),所以你仍然可以拥有多个数据库但是每个数据库只能有一个表或一个类,但是如果很多表仍然只是暂时的解决方案,它确实会产生巨大的开销......

这里是" Binds"的参考。 - http://flask-sqlalchemy.pocoo.org/2.0/binds/#binds

以下是配置:

SQLALCHEMY_DATABASE_URI =' sqlite://///main.db'

SQLALCHEMY_BINDS = { '表1':'源码://///DB1.db' ;, '表2':'源码://///DB2.db' ;, }

以下是模型:

class table1(db.Model):

__tablename__ = "table1"
__bind_key__='table1'

class table2(db.Model):

__tablename__ = "table2"
__bind_key__='table2'