Как получить доступ к контексту приложения Flask из встроенного приложения Dash при использовании шаблона фабрики приложений? - PullRequest
2 голосов
/ 25 июня 2019

Я создаю веб-приложение, используя Flask и Dash.Основное приложение Flask обрабатывает вход в систему пользователя и аутентификацию, а также защищает маршруты приложения Dash.Приложение Dash обслуживается из приложения Flask.

Основное приложение Flask было создано на примере учебника Flask Mega (https://github.com/miguelgrinberg/microblog), с шаблоном фабрики приложений. Я удалил все, кроме login /на этом этапе все работает нормально.

Затем я добавил простое приложение Dash в приложение Flask, следуя приведенному ниже примеру: https://github.com/okomarov/dash_on_flask. Доступ к приложению Dash можно получить на / dashboard, иПанель управления должным образом защищена от несанкционированного доступа и перенаправляется обратно на главную страницу входа в Flask, как и ожидалось.

Теперь моя задача - получить доступ к контексту приложения Flask и другим вещам, таким как сеанс базы данных, из приложения Dash.Именно поэтому приложение Dash может получать доступ и отображать информацию из основной базы данных.

В настоящее время я застрял, пытаясь следовать примерам, которые я нашел в Интернете, и узнать, как адаптировать их к конкретному шаблону моего приложения.

Я пытался следовать приведенным здесь примерам: https://github.com/plotly/dash/issues/214#issuecomment-391223557.

ОднакоВсе эти примеры, похоже, основаны на плоской структуре приложения, в которой приложения Flask и Dash создаются в одном файле.

Весь мой код находится здесь: https://github.com/danielcopelin/dacy-budget

НаНа данный момент мое основное приложение Flask выглядит так:

dacybudget.py

from app import create_app, db
from app.models import User

app = create_app()


@app.shell_context_processor
def make_shell_context():
    return {'db': db, 'User': User}

create_app () выглядит так:

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

    register_dashapps(app)

    db.init_app(app)
    migrate.init_app(app, db)
    login.init_app(app)
    mail.init_app(app)
    bootstrap.init_app(app)

... и register_dashapps () выглядиткак:

def register_dashapps(app):
    from app.dashapp1.layout import layout
    from app.dashapp1.callbacks import register_callbacks

    # Meta tags for viewport responsiveness
    meta_viewport = {
        "name": "viewport",
        "content": "width=device-width, initial-scale=1, shrink-to-fit=no",
    }
    external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
    dashapp1 = dash.Dash(
        __name__,
        server=app,
        url_base_pathname="/dashboard/",
        assets_folder=get_root_path(__name__) + "/dashboard/assets/",
        meta_tags=[meta_viewport],
        external_stylesheets=external_stylesheets,
    )

    dashapp1.title = "Dashapp 1"
    dashapp1.layout = layout
    dashapp1.url_base_pathname = "/dashboard/"  # I dont know why I had to do this
    register_callbacks(dashapp1)
    _protect_dashviews(dashapp1)

Изнутри app.dashapp1.layout и app.dashapp1.callbacks Я хочу иметь доступ к сеансу и базе данных основного приложения Flask и т. д.

Если я попытаюсьразличные импорта из app.dashapp1.layout, например «from .. import db», а затем попытаться что-то сделать с этим объектом db, я получаю сообщения об ошибках типа:

RuntimeError: Приложение не найдено.Либо работайте внутри функции представления, либо передавайте контекст приложения.См. http://flask -sqlalchemy.pocoo.org / contexts / .

Может кто-нибудь предложить какие-либо предложения о том, как решить эту проблему?

1 Ответ

0 голосов
/ 27 июня 2019

Мне удалось решить мою проблему.Я изо всех сил пытался понять, где на стороне Dash приложения можно было получить доступ к контексту основного приложения Flask, чтобы я мог предоставить Dash доступ к базе данных.Оказывается, это можно сделать с помощью функции register_callbacks () и реальных функций обратного вызова, определенных в ней следующим образом:

def register_callbacks(app):
    from app import db
    from app.models import Transaction
...
    @app.callback(
            Output("main", "children"),
            [Input("transaction_table", "data_previous")],
            [
                State("transaction_table", "data"),
                State("transaction_table", "page_current"),
            ],
        )
        def update_database_and_generate_table(old_table_data, table_data, page_current):
            with app.server.app_context():
                if old_table_data is not None:
                    update_changed_data(old_table_data, table_data)
                transactions = db.session.query(Transaction)
                df = pd.read_sql(transactions.statement, transactions.session.bind)

Чтобы это работало, необходимо внести другое изменение в код моего оригинала.вопрос.В функции create_app () вам необходимо зарегистрировать приложение Dash после инициализации базы данных:

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

    db.init_app(app)
    migrate.init_app(app, db)
    login.init_app(app)
    mail.init_app(app)
    bootstrap.init_app(app)

    app = dashapp.add_dash(app)
...

Полный рабочий пример находится здесь: https://github.com/danielcopelin/dacy-budget

...