Dynamic layout with multi page app

Hello everybody,

I’m trying to build a multipage app, where each app can have a dynamic layout, but multipage apps (per URL Routing and Multiple Apps | Dash for Python Documentation | Plotly) don’t seem to be compatible with the approach suggested to use dynamic layout (the Updates on page load section of the docs at Live Updates | Dash for Python Documentation | Plotly).

Does anybody have any good suggestions for how to combine the two approaches so that I can have a multipage app whose individual page layouts are dynamic?

The top layer app layout looks like this (in index.py):

app.layout = html.Div([
    html.Div(
        [
            dcc.Location(id='url', refresh=False),
        ],
        id="toc"
    ),
    html.Div(id='page-content'),
])

my callback (in index.py) looks like:

app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/apps/cumulative_pnl':
        return cumulative_pnl.layout
    elif pathname == '/apps/cumulative_pnl_bookmarks':
        return cumulative_pnl_bookmarks.layout
    else:
        return toc_layout

Inside of my cumulative_pnl.py module, I have a function called return_layout that returns the layout that I want to use (simplified here) and then I assign it to layout (cumulate_pnl.layout)

return_layout():
     return html.Div(
                     [
                                 dcc.Input(
                                    id='start_date',
                                    placeholder='YYYY/MM/DD',
                                    type='text',
                                    value=datetime.date.today().strftime('%Y/%m/%d'),
                                    debounce=True,
                                ),
                                'end_date',
                                dcc.Input(
                                    id='end_date',
                                    placeholder='YYYY/MM/DD',
                                    type='text',
                                    value=datetime.date.today().strftime('%Y/%m/%d'),
                                    debounce=True,
                                ),
                    ],
             )

layout = return_layout

but I get the following exception:

Exception on /_dash-update-component [POST]
Traceback (most recent call last):
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/flask/app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/flask/app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/dash/dash.py", line 1032, in dispatch
    response.set_data(func(*args, outputs_list=outputs_list))
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/dash/dash.py", line 1002, in add_context
    _validate.fail_callback_output(output_value, output)
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/dash/_validate.py", line 251, in fail_callback_output
    _validate_value(val, index=i)
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/dash/_validate.py", line 246, in _validate_value
    toplevel=True,
  File "/home/mhale/.virtualenvs/dash_release/lib/python2.7/site-packages/dash/_validate.py", line 200, in _raise_invalid
    bad_val=bad_val,
InvalidCallbackReturnValue: The callback for `<Output `page-content.children`>`
returned a value having type `function`
which is not JSON serializable.


The value in question is either the only value returned,
or is in the top level of the returned list,

and has string representation
`<function return_layout at 0x7f64c3396c08>`

In general, Dash properties can only be
dash components, strings, dictionaries, numbers, None,
or lists of those.
10.4.150.20 - - [21/Jul/2020 15:13:10] "POST /_dash-update-component HTTP/1.1" 500 -

I’ll note that if in

app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/apps/cumulative_pnl':
        return cumulative_pnl.layout
    elif pathname == '/apps/cumulative_pnl_bookmarks':
        return cumulative_pnl_bookmarks.layout
    else:
        return toc_layout

For the pathname == ‘/apps/cumulative_pnl’ conditional, I return cumulative_pnl.return_layout() instead, it seems to work ok, even though the docs say to use the function object itself rather than call the function?

I have concerns that I’m doing something wrong here since the documentation seems to warn against calling the function vs defining layout as the function object itself

1 Like