在Flask出厂设置中反映不同的数据库

时间:2019-07-04 09:56:58

标签: python python-3.x flask flask-sqlalchemy

我想在我的应用程序中使用Flask的应用程序工厂机制。我的想法是,我在某些蓝图中使用的数据库位于不同的位置,因此我使用绑定来指向它们。这些表本身正在生产中并且已经在使用中,因此我需要对其进行反映,以便在我的应用程序中使用它们。

问题是由于应用程序上下文,我无法使反射功能正常工作。我总是得到这样的消息:我正在应用程序上下文之外工作。我完全理解这一点,并且看到该db确实在外面,但是对如何使用它不再有任何想法。

我尝试了通过current_app将应用程序传递给我的models.py的其他变体,但是没有任何效果。

config.py:

class Config(object):

    #Secret key
    SECRET_KEY = 'my_very_secret_key'

    ITEMS_PER_PAGE = 25

    SQLALCHEMY_BINDS = {
        'mysql_bind': 'mysql+mysqlconnector://localhost:3306/tmpdb'
    }
    SQLALCHEMY_TRACK_MODIFICATIONS = False

main.py:

from webapp import create_app

app = create_app('config.Config')

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

webapp / init .py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config_object):
    app=Flask(__name__)
    app.config.from_object(config_object)

    db.init_app(app)

    from main import create_module as main_create_module
    main_create_module(app)

    return app

webapp / main / init .py:

def create_module(app):
    from .controller import blueprint
    app.register(blueprint)

webapp / main / controller.py:

from flask import Blueprint, render_template, current_app as app
from .models import db, MyTable # <-- Problem might be here ...

bluerint = Blueprint('main', __name__)

@blueprint.route('/'):
def index():
    resp = db.session.query(MyTable)\
            .db.func.count(MyTable.versions)\
            .filter(MyTable.versions =! '')\
            .group_by(MyTable.name).all()
    if resp:
        return render_template('index.html', respo=respo)
    else:
        return 'Nothing happend'

webapp / main / models.py:

from .. import db # <-- and here ...

db.reflect(bind='mysql_bind')

class MyTable(db.Model):
    __bind_key__ = 'mysql_bind'
    __table__ = db.metadata.tables['my_table']

预期结果将是使反射在不同的蓝图中起作用。

2 个答案:

答案 0 :(得分:2)

让它正常工作,这里是完整的解决方案: https://github.com/researcher2/stackoverflow_56885380

我已经使用sqllite3进行测试,运行create_db.py脚本来设置数据库。使用debug.sh运行flask,因为最近的版本似乎不再只在__main__内包含app.run()。

说明

据我了解,如果您需要在单个应用程序或多个应用程序中多次使用视图,蓝图只是将多个视图组合在一起的一种方法。您可以根据需要添加其他路由前缀。

db对象不与蓝图相关联,它与提供配置信息的应用程序相关联。进入蓝图视图后,您将可以使用自动可用的相关应用程序上下文访问db对象。 关于db.reflect,您需要在create_app内进行调用并将其传递给应用对象(首选),或者将应用导入到意大利面条模型中。

可以使用绑定访问多个DB,如所示。

因此,您的蓝图将有权访问所有导入的表,并且flask-sqlalchemy根据绑定知道要使用哪个数据库连接。

我通常是明确定义表的爱好者,因此您可以在代码完成中访问ORM对象和字段。您是否有很多表/字段,或者是否正在创建某种东西来查询表元数据,以便在任何模式下实现完全自动化?就像模式查看器或类似的东西。

这可能对其他来此帖子的人有用: https://flask-sqlalchemy.palletsprojects.com/en/2.x/contexts/

答案 1 :(得分:1)

太棒了!非常感谢你。得到它也起作用。您的提示给了我一个寻找另一种方法的提示:

@blueprint.route('/')
def index():

    # pushing app_context() to import MyTable
    # now I can use db.reflect() also in models.py
    with app.app_context():
        from .models import MyTable

    results = db.session.query(MyTable).all()
    print(results)
    for row in results:
        print (row)
        print(row.versions)
        print(row.name)

    if results:
        return render_template('my_table.html', results=results)
    else:
        return 'Nothing happend'

然后可以在models.py中进行反射。您发布的链接确实很有帮助,不知道为什么我自己没有迷路……

无论如何,我现在比以前有更多的机会!

干杯,队友!