Update dash layout using REST API

Iā€™ve created some scripts using Python dash library.
It creates graphs using some testing json information(these jsons are results of another Python scripts - letā€™s call them clients).
This part works fine.

Also, I have a REST API which runs on the separate host. It should collect results from clients and displays them using Dash.

My workflow looks like this:

  • Iā€™m running scripts on different clients.
  • All these clients collect their statistics (and are able to create layouts in dash format, if needed)
  • Sends results of execution from each client into REST API (json or dash-layout)
  • A well-formatted report should be available using the browser. E.g.:

http://localhost:8050/client_reports/

Itā€™ll be improved, but for the first version it might show the result of the latest client (in the final version all reports from all clients will be available)

So, currently I have:

  • Scripts on clients which runs fine

  • Functionality which generates json or dash-layout statistics (e.g.:
    "Div(children=[H1(children='My fantastic report', style={'color': '#7FDBFF', 'textAlign': 'center'}), style={'backgroundColor': '#111111'})"

  • REST API (Flask app) - I can easily add endpoints for GET/POST request with dash-layout string.

  • Dash application which runs on the separate endpoint of my web server with a basic dash-layout.

The question is:
Is there any ability to update dash-layout during runtime?
E.g.: Iā€™ve started my REST API with the base layout.
After then Iā€™ll run my scripts on the client side, collect statistics, send these data into additional endpoint using POST request.

Then there should be some callback, etc. in the dash application side, which serves data using GET requests (it might be implemented in another way, but I think in this direction) and updates:
app.layout = requests.get('http://localhost:8050/client_reports_data/")

And sending new requests via browser into an appropriate endpoint should display updated info:
http://localhost:8050/client_reports/

Any ideas?

You can assign a function to app.layout which will get called each time the page is loaded, see the Dash docs.

In your case, you could make a request to your API to determine the layout when the page is refreshed, something like this

def serve_layout():
    # query your api
    # build layout depending on results
    return layout


app.layout = serve_layout

Would that do what you need?

1 Like

Is it enough just to return layout as a string?

No, the layout must be a Dash Component, e.g:

def serve_layout():
    # query your api
    # build layout depending on results
    return html.Div(...)

app.layout = serve_layout

This new layout is generated every time the page is called or the page is refreshed (assuming no browser cache issues).

Hi there!

Just checking if @pivanchy had found a resolution to this issue? Iā€™m on the exact same problem except I need my Dash app to be able to receive a request so that it knows where to pull the data from.

Steps:

  1. Some server sends information to Dash server on id of data to request
  2. Dash makes a GET (this part seems do-able)
  3. Renders graph

Thanks!

Austin

I believe the answer was a pretty simple call-back to the Flask supporting Dash

app = dash.Dash(name, external_stylesheets=external_stylesheets)
server = app.server
.
.
.

@server.route(ā€™/inputā€™)
def student():
return render_template(ā€˜student.htmlā€™)

@server.route(ā€™/resultā€™,methods = [ā€˜POSTā€™])
def result():
if request.method == ā€˜POSTā€™:
result = request.form
return render_template(ā€œscores.htmlā€,result = result)

Serve main app layout using Dash

app.layout = html.Div(children=[
#html.H1(test_requests()),
dcc.Location(id=ā€˜urlā€™, refresh=False),
# index_page_layout,
html.Div(id=ā€˜page-contentā€™)
],
)

@austinpowers Iā€™m looking to update the Dash layout at runtime by an external POST request. I didnā€™t quite get the final part of your answer. What exactly is ā€˜test_requests()ā€™? And how should I pass the POST request body to the dash layout? Thanks in advance.