Dash#
Dash is a productive Python framework for building web applications. Written on top of Flask, Plotly.js, and React.js, Dash is ideal for building data visualization apps with highly custom user interfaces in pure Python. It's particularly suited for anyone who works with data in Python.
Deploying#
Dash apps can be deployed with the
rsconnect-python
package. See the Publishing with
rsconnect-python section for
details.
Example apps#
An example Dash app is available on GitHub.
To deploy the example with rsconnect-python
:
git clone https://github.com/sol-eng/python-examples
rsconnect deploy dash -n <saved server name> --entrypoint app:app python-examples/dash-app/
There are also a number of Dash example apps available from Plotly. Some of them require Python 2 and others use Python 3; please ensure that you run them locally before deploying to Connect.
git clone https://github.com/plotly/dash-sample-apps
rsconnect deploy dash -n <saved server name> --entrypoint app:app dash-sample-apps/apps/<app name>/
When deploying a Dash app, ensure that you specify the correct entrypoint
for the specific app you are deploying.
The example applications in this section have their source code in a file named app.py
,
and within that file, the Dash application object is named app
. So the entrypoint
specified here is app:app
. If the main source file or application object is named
differently, you will need to specify a different entrypoint so that RStudio Connect
can locate the application object to serve. See the
documentation on entrypoints
for more information.
Multi-page apps#
The Dash documentation includes an example of an app that consists of multiple pages, and an index page for navigation. To deploy a multi-page app on RStudio Connect, you must use Dash's get_relative_path
and strip_relative_path
functions to implement the navigation. For example:
import dash
import dash_core_components as dcc
import dash_html_components as html
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
[
# represents the URL bar, doesn't render anything
dcc.Location(id="url", refresh=False),
dcc.Link("Navigate to index", href=app.get_relative_path("/")),
html.Br(),
dcc.Link('Navigate to "/page-2"', href=app.get_relative_path("/page-2")),
html.Br(),
dcc.Link('Navigate to "/page-3"', href=app.get_relative_path("/page-3")),
# content will be rendered in this element
html.Div(id="page-content"),
]
)
@app.callback(
dash.dependencies.Output("page-content", "children"),
[dash.dependencies.Input("url", "pathname")],
)
def display_page(pathname):
pathname = app.strip_relative_path(pathname)
return html.Div([html.H3("You are on page {}".format(pathname or "index"))])
if __name__ == "__main__":
app.run_server(debug=True)
Note
Content URL paths for multi-page Dash apps do not update based on a set vanity URL.
For example, setting your application vanity URL to /multi-page-dash/
will make the
index page available at that location, but /multi-page-dash/page-2
will not be accessible.
page-2
will only be accessible via the base content URL, .../content/{GUID}/page-2
.
User meta-data#
Dash apps can access the username and the names of the groups of the current
logged in user by parsing the RStudio-Connect-Credentials
request header.
Note
Your Dash app should access the RStudio-Connect-Credentials
header value
via the flask.request
object's headers
property. This value is populated
from the HTTP_RSTUDIO_CONNECT_CREDENTIALS
environment variable present in the underlying WSGI environ.
This simple Dash app shows how to access and use the user credentials from the
RStudio-Connect-Credentials
header:
# -*- coding: utf-8 -*-
import json
import dash
import dash_core_components as dcc
import dash_html_components as html
import flask
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
id="salutation",
options=[
{"label": "Hello", "value": "Hello"},
{"label": "Greetings", "value": "Greetings"},
{"label": "Aloha", "value": "Aloha"},
],
searchable=False,
clearable=False,
value="Hello"
),
html.P(id="greeting")
])
def get_credentials(req):
"""
Returns a dict containing "user" and "groups" information populated by
the incoming request header "RStudio-Connect-Credentials".
"""
credential_header = req.headers.get("RStudio-Connect-Credentials")
if not credential_header:
return {}
return json.loads(credential_header)
@app.callback(
Output(component_id="greeting", component_property="children"),
[Input("salutation", "value")]
)
def greeting(salutation):
user_metadata = get_credentials(flask.request)
username = user_metadata.get("user")
return "%s, %s." % (salutation, username or "stranger")
if __name__ == "__main__":
app.run_server(debug=True)
User and Group uniqueness#
Most environments have unique usernames where each user
identifies a single
user and groups
the name of the groups the user is a member of.
However, in large organizations with hundreds of users and groups, this may not be true. See the Admin Guide sections Credentials for Content for more information.