10

I'm using the Python library Dash and the documentation claims that it doesn't support the ability to write raw html with the dashboard html code. Is there a known work around to this (something like passing dcc.Graph into render_template() with Flask?).

The code snippet I would like to migrate to an Jinja template file is:

app.layout = html.Div(className='ui container', children=[
    html.H1('Locations', className=''),
    html.Div(id='text-content'),
    dcc.Graph(id='map', figure={
        'data': [{
            'lat': df['LAT'],
            'lon': df['LONG'],
            'marker': {
                'color': df['YEAR'],
                'size': 8,
                'opacity': 0.6
            },
            'customdata': df['NO'],
            'type': 'scattermapbox'
        }],
            },
            'hovermode': 'closest',
            'margin': {'l': 0, 'r': 0, 'b': 0, 't': 0}
        }
    })
])
Nils
  • 2,665
  • 15
  • 30
deko
  • 337
  • 3
  • 12

2 Answers2

0

I have been here before and asked this question myself which I went on to answer here: Plotly.offline plot output_type='div' not working inside HTML - How to embed Plotly to HTML

In a nutshell, to get a plotly chart rendered via a Flask view you can do the following (taken from the above link)

  1. Create a chart
  2. Call pyo.plot() as normal passing through the fig, output_type='div' and include_plotlyjs=False
  3. Have that output to a variable passed through Markup() (import from flask)
  4. Have the Markup(variable) passed through the render_template like you would a form
  5. Have the variable rendered in the html using {{ jinja template }}

A bit more of a practical demonstration:

def my_bar_chart():
    *snip irrelevant*
    my_bar_chart = pyo.plot(fig, output_type='div', include_plotlyjs=False)
    return Markup(my_bar_chart)

Now import your function to your app.py / wherever your views are and pass it through render template as you would any form, for example.

Here is an example:

def my_page():
    my_bar_chart_var = my_bar_chart()
    return render_template('my_page.html',
                            bar_chart_1=my_bar_chart_var)

Then on the html for that page simply pass through bar_chart_1 in a jinja template like so:

{{ bar_chart_1 }}
Paul Wilson
  • 562
  • 5
  • 16
0

Here's what I did to build a Dash template from an existing Flask, Jinja template.

In case you're wondering, I built a hybrid web app that uses both Flask and Dash.

First extend your "base.html" template into a Dash-specific template (e.g. "base_dash.html"), using HTML comments for the things Dash needs to replace (e.g. {%metas%} or {%app_entry%}:

{% extends "base.html" %}

{% block head %}
  <!-- metas -->
  <title>
    <!-- title -->
  </title>
  <!-- favicon -->
  <!-- css -->
{% endblock %}

{% block body %}
  <!-- app_entry -->

<footer>
  <!-- config -->
  <!-- scripts -->
  <!-- renderer -->
</footer>
{% endblock %}

Back in Python, set up the Dash app:

    dashapp = dash.Dash()

    # FYI, you need both an app context and a request context to use url_for() in the Jinja2 templates
    with app.app_context(), app.test_request_context():
        layout_dash = pathlib.Path(get_root_path(__name__)).joinpath("templates").joinpath("base_dash.html")

        with open(layout_dash, "r") as f:
            html_body = render_template_string(f.read())

        comments_to_replace = ("metas", "title", "favicon", "css", "app_entry", "config", "scripts", "renderer")
        for comment in comments_to_replace:
            html_body = html_body.replace(f"<!-- {comment} -->", "{%" + comment + "%}")

        dashapp.index_string = html_body
Sean McCarthy
  • 4,838
  • 8
  • 39
  • 61