在Flask应用程序中访问应用程序配置变量

14

我有一个 Flask 应用程序,它看起来像这样:

myapp
-- application.py
-- models.py
-- queries.py
-- routes.py
-- settings.py

application.py看起来像这样:

from flask import Flask
from myapp import routes

def create_app(config_object):

    app = Flask(__name__)
    app.config.from_object(config_object)

    app.register_blueprint(routes.main)

    return app

queries.py看起来像这样

from myapp.models import User

class QueryConnection(DATABASE_URI):
    self.engine = create_engine(DATABASE_URI)
    self.session = sessionmaker(bind=self.engine)
    self.Session = self.session()

    def get_all_users(self):
        return self.Session.query(User).all()

routes.py文件如下:

from flask import current_app, Blueprint, render_template
from myapp import queries
main = Blueprint('main', __name__, url_prefix='/')

query_connection = queries.QueryConnection(current_app.config['DATABASE_URI'])

@main.route("/")
def index():
    return render_template('index.jinja2', list=query_connection.get_all_users())

models.py看起来像这样:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id           = Column(Integer, primary_key=True)
    name         = Column(String)

我希望在routes.py中获取当前应用的config['DATABASE_URI']以便查询数据库,但我不知道如何从application.py传递app上下文到queries.py。我尝试在application.py中使用以下内容:
with app.app_context():
    app.register_blueprint(main)

但是我收到了"working outside of application context"的错误。任何其他东西都会给出相同的错误。

我想将查询封装在自己的类中,以便我可以在不同的上下文中传递数据库URI,比如测试中。

2个回答

4

您需要导入文件,从调用create_app方法的地方导入。我猜测这个地方应该是application.py文件。

--- D_file.py

app = create_app(your_config)

--- queries.py

from D_file import app

DB_URI = app.config['DATABASE_URI']

1
这有点像先有鸡还是先有蛋的问题。应用程序包含对查询的调用。我必须制作应用程序来引用它,但是在我制作它的时候,我已经查询了数据库。因此,我需要一种访问配置变量而不调用应用程序的方法。我有一种感觉,这就是 flask.current_app 的用途。 - pspencer
1
看起来是一个糟糕的设计决策。可以参考 https://github.com/miguelgrinberg/flasky 获取一些灵感。 - CESCO
@CESCO 我已经阅读了你的代码库,那么基本上唯一的方法就是导入包然后传递 app?没有更好的访问方式吗?current_app 的目的是什么? - TomSawyer
@TomSawyer 我在 Flask 方面已经过时了。 - CESCO

-3
为什么在SQLAlchemy设置中要涉及Flask应用程序?你可以直接使用可用的配置对象。然后,您可以将会话附加到Flask全局对象或动态创建会话。
在queries.py中。
import get_config from config

config_object = get_config()
engine = create_engine(config_object['DATABASE_URI'])
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)

def get_all_users():
    session = Session()
    users = session.query(User).all()
    session.close()
    return users

在你的应用工厂中:

from flask import Flask, g
from myapp import routes
from myapp.queries import Session

def create_app(config_object):

    app = Flask(__name__)
    app.config.from_object(config_object)

    app.register_blueprint(routes.main)

    # automatically set up and close a session for each request
    @app.before_request
    def before_request(response):
        g.session = Session()

    @app.after_request
    def after_request(response):
        g.session.close()

    return app

在你的例子中,config对象似乎是硬编码到queries.py模块中的。如果我想要一个不同的对象,比如说用于测试,该怎么办? - pspencer
你可以从某种工厂函数中获取配置。在该函数中,您将有一些逻辑来确定您所处的环境,并返回一个适当的对象。 - jumbopap
我不太明白你的意思。我最终想要返回的适当对象是一个 sqlalchemy 会话,它根据我在 app.config 中指定的环境知道要查询哪个数据库。 - pspencer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接