Flask Dash App
This is a demo application that can serve as a starter project template.
It allows you to
- serve several individual Dash apps from a single Flask application,
- add core Flask logic, such as authentication with Flask-Login, generating assets with Flask-Assets, sending email with Flask-Mail, etc.,
- integrate individual Dash apps in a global layout defined in Jinja templates.
Overview
- What's included
- Getting started
- Examples
- Development
- Global layout: integration of individual dash apps
- Credits
- License
What's included
Docker base image: https://github.com/tiangolo/uwsgi-nginx-flask-docker
Getting started
git clone https://github.com/tzelleke/flask-dash-app.git
cd flask-dash-app
cp .env.example .env
docker-compose up -d
Integrate your Dash app
Let us go through the steps to integrate a simple demo Dash app. Here is the source code for a rudimentary Dash app.
import dash
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div(children=[html.H1(children="Hello Dash"), ])
if __name__ == "__main__":
app.run_server(debug=True)
Save it as demo.py
in the app/dash/
folder.
Change the code in demo.py
to:
from .dash import Dash
import dash_html_components as html
app_layout = html.Div(children=[html.H1(children="Hello Dash"), ])
def init_dash(server):
dash_app = Dash(server=server, routes_pathname_prefix="/demo/", )
dash_app.layout = app_layout
return dash_app.server
if __name__ == "__main__":
app = Dash(__name__)
app.run_server(debug=True)
Register the Dash app with the main Flask application in app/main.py
.
...
with app.app_context():
from .dash import demo
app = demo.init_dash(app)
...
Add the new route to the global navbar in app/templates/partials/navbar.html
...
<a class="dropdown-item" href="/demo/">Simple Demo</a>
...
Development
Manage python dependencies (using Poetry)
docker-compose run web poetry update # ... or any other poetry command
Global layout: integration of individual dash apps
This starter integrates individual dash apps into a global layout provided by Flask/Jinja templates. This is achieved by
overriding the interpolate_index
method from the core Dash
class.
# app/dash/dash.py
import dash
from markupsafe import Markup
from flask import render_template
class Dash(dash.Dash):
def interpolate_index(
self,
metas="",
title="",
css="",
config="",
scripts="",
app_entry="",
favicon="",
renderer="",
):
return render_template(
"dash.html",
metas=Markup(metas),
css=Markup(css),
dash_config=Markup(config),
scripts=Markup(scripts),
app_entry=Markup(app_entry),
renderer=Markup(renderer),
)
Note: markupsafe.Markup
is used to prevent Jinja from escaping the Dash-rendered markup.
Note: config
is mapped to dash_config
to avoid shadowing the global Flask config in the Jinja environment.
The corresponding Jinja template in app/templates/dash.html
extends the base template and injects the provided markup
via Jinja template blocks.
{# app/templates/dash.html #}
{% extends 'base.html' %}
{% block meta %}
{{ super() }}
{{ metas }}
{% endblock %}
{% block styles %}
{{ super() }}
{{ css }}
{% endblock %}
{% block content %}
{{ app_entry }}
{% endblock %}
{% block scripts %}
{{ super() }}
{{ dash_config }}
{{ scripts }}
{{ renderer }}
{% endblock %}
Credits
- https://hackersandslackers.com/plotly-dash-with-flask/
- https://github.com/tiangolo/uwsgi-nginx-flask-docker
- https://www.merixstudio.com/blog/deploying-docker-heroku-tutorial/
License
See the LICENSE file for license rights and limitations (MIT).