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)

User meta-data

Dash apps can access the username and groups of the current logged in user by parsing the RStudio-Connect-Credentials request header.

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. In large organizations with hundreds of users, it is possible to have two users with, for example, the same last name and initials, which could result in a duplicated username. If you're expecting such a large number of logged in users to access your Dash application, please be sure to consult your administrator to confirm whether this condition is possible in your environment. Note that groups may suffer the same issue of duplicates names when users are authenticating against some providers, Azure in particular. If you want to ensure uniqueness of the user or group identifiers RStudio Connect should be configured with the option Authorization.ContentCredentialsUseGUID. When enabled, your content will receive the user and groups GUIDs instead of their names in user and groups. Not only are these values guaranteed to be unique but they can also be used to query for additional information about the user and groups using the Connect Server API.

Group meta-data is populated when using most authentication providers with the exception of LDAP. This happens because group memberships are only stored in the LDAP server.

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)