Update index_string

I have a running dash app. In the debugger, I can get the app with the function get_app(). In the app I get, I can see and modify the index_string, but I cannot find a way to update the app attached to the Flask server. Is there a way to update the index_string once the dash app has been initialized?

Ok, I found a solution, but it is super hacky, and I really would like something a bit more robust and elegant, so whoever has an idea, please share it!

The solution is by setting your index_page like this: your app exists in dash.dcc._dash._get_app.APP

You can modify it from within a dash callback code, from where the variable is visible.

and you can set the index_page attribute directly in the dash_app using setattr like this:

html_body = render_template_string(html_layout, variable_for_jinja=value)
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 + "%}")
setattr(dash.dcc._dash._get_app.APP,"index_string",new_index_page)
1 Like

Hello @Giuliozoo,

Welcome to the community!

Glad you figured out a solution to your problem. My only question is, why are you trying to alter the index strings? Could these perhaps be handled by setting up functions inside of the routings? (Including the Flask server)

Dear @jinnyzor,
I tried to find another solution, but according to my (little) understanding of the integration of Flask and Dash, the webpage is rendered upon the call of the “routes_pathname_prefix” of the dash_app. As such, I could not find a way to update the part of the page requiring a jinja re-rendering without changing the index_string in the dash app.

To add a bit more details:
to integrate Dash with Flask, I pass Flask app as Dash server, and get back the Flask app with the Dash app integrated in it, also taking advantage of Jinja.
If I want to add a Jinja template, I can pass the HTML template to the code initializing Dash. The index string shall contain the {%" + filed + "%} required by Dash, but rendering the template will escape that code.

A trick for a solution of the problem is implemented when HTML is enriched with comments, which are ignored by Jinja during the rendering, and then replaced in the code with the fields for Dash before setting the index_string upon Dash app initialization. This effectively works, the dash app is well integrated in the Flask server, and the Jinja template is inegrated and rendered.

Here some code to frame this a bit more concretely:

def init_dashboard(server,url):
"""Create a Plotly Dash dashboard."""
dash_app = dash.Dash(
    server=server,
    routes_pathname_prefix=url,
    external_stylesheets=[
        "/static/dist/css/styles.css",
        "https://fonts.googleapis.com/css?family=Lato",
    ],
)
 # Both app context and a request context to use url_for() in the Jinja2 templates are needed
with server.app_context(), server.test_request_context():
    #items = Item.query.all()
    html_body = render_template_string(html_layout)

    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 + "%}")

    dash_app.index_string = html_body
# Load DataFrame
df = create_dataframe()

# Create Layout
dash_app.layout = my_layout
init_callbacks(dash_app)
return dash_app.server

With the layout in HTML:


    html_layout = """
{% extends "base.html" %}

{% block title %}
Calculator 
{% endblock %}


 {% block content %}
 <body class="dash-template">
            <header>
              <div class="nav-wrapper">
                <!-- <a href="/">
                    <img src="/static/img/logo.png" class="logo" />
                    <h1>Plotly Dash Flask Tutorial</h1>
                  </a> -->
                <nav>
                </nav>
            </div>
            </header>
            <!-- app_entry -->
            <footer>
              <!-- config -->
              <!-- scripts -->
              <!-- renderer -->
            </footer>
        </body>
 {% endblock %}
"""

Are you aware of a better approach, or of a better and more robust way to update the index_string?

1 Like

Ooo. That’s fun.

You wanted to add base html rendering from the flask server. And then pass that new template on to be rendered by Dash. I don’t know that there is another way to do this. Unless you passed all of the flask alterations that you made to Dash.

1 Like