How to abstract dash plotly component into another file with a callback? - python

Currently, I have my application python file separated with the specific component in the Django framework.
I have seen a lot of examples writing each component with callback in the same file with the app python file. I am wondering how to write the update_output_div() function in a file with callback and let the app call it? Thank you so much!
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
...
])
#app.callback(
Output(component_id='my-output', component_property='children'),
Input(component_id='my-input', component_property='value')
)
def update_output_div(input_value):
return 'Output: {}'.format(input_value)
if __name__ == '__main__':
app.run_server(debug=True)

You could create a function that takes your app as a parameter and put your decorated function inside this function:
def init_callback(app):
#app.callback(
Output(component_id="my-output", component_property="children"),
Input(component_id="my-input", component_property="value"),
)
def update_output_div(input_value):
return "Output: {}".format(input_value)
Then you could call the function like this after defining app.layout like this:
init_callback(app)

Related

cant get the url in a dash app with request

I have tried all possibilities, but I can't get it to read the URL in a Python Dash application. Below is an attempt, which unfortunately does not work: the first part of the URL comes, but the back part is always filled with "_dash-update-component".
Calling in the browser with "http://127.0.0.1:8050/langage=EN" always brings only:
http://127.0.0.1:8050/_dash-update-component
anyone maybe have an idea?
import dash
from dash import html
from dash.dependencies import Input, Output
from flask import request
app = dash.Dash()
app.layout = html.Div([
html.Button("Get URL", id="get_url"),
html.Div(id='output-url')
])
#app.callback(
Output(component_id='output-url', component_property='children'),
[Input(component_id='get_url', component_property='n_clicks')]
)
def update_output(n_clicks):
if n_clicks is None:
raise dash.exceptions.PreventUpdate
else:
return request.url
if __name__ == '__main__':
app.run_server(debug=True)

Spinner removed when using long_callback in Dash app

My app works fine when I use the regular Dash callback, but I am currently forced to use long_callback. In this case, my spinner (dcc.Loading) disappears almost instantly - although, ironically, this seems to be a really useful place for a spinner. I have tried to create a minimal example below.
Am I misusing the spinners or is this a bug?
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
from dash.long_callback import DiskcacheLongCallbackManager
import diskcache
import time
cache = diskcache.Cache('./cache')
long_callback_manager = DiskcacheLongCallbackManager(cache)
app = dash.Dash(
__name__,
long_callback_manager=long_callback_manager,
)
app.layout = html.Div(children=[
dcc.Slider(id='my_slider', min=1, max=10, step=1, value=5),
dcc.Loading(
html.Div(id='my_div', children=['Start']),
),
])
#app.long_callback(
Output('my_div', 'children'),
Input('my_slider', 'value'),
interval=2000,
)
def update_div(slider_value):
time.sleep(5)
return f'Done loading: {slider_value}'
if __name__ == '__main__':
app.run_server(debug=True)
I have tried to set the loading_state/is_loading property in the running argument of the long_callback, but I haven't succeeded. Maybe it's not a "setable" property?
Not sure if this is the solution you are looking for, but I have discovered a method that works with dash bootstrap components using the dbc.Spinner in conjunction with the running keyword argument of the long_callback.
First, create a div where you want the spinner to appear, give it a unique id name and set its children equal to None. For me, I used a dbc.Row(dbc.Col()) instead of a div, but it should work the same. Then you will need to set the running keyword argument of the long_callback to output a dbc.Spinner. The following code is currently working for me. I have removed a lot of code, so ignore the inputs, ouputs and lack of layout components. Pay attention to the running kwarg.
app.layout = dbc.Container(dbc.Row(dbc.Col(id='fs_spinner', children=None)))
#app.long_callback(
output=(
Output("full_search_predictions", "data"),
Output("full_results_query", "data"),
),
inputs=[
Input("submit_button", "n_clicks"),
Input("search_query", "value"),
],
running=[
(Output('fs_spinner', 'children'), dbc.Spinner(size='md'), None)
],
interval=20000,
prevent_initial_call=True,
)
Here is what is happening. When the the long_callback begins, it returns a dbc.Spinner() to the children component of the fs_spinner. Once the callback is complete, it then returns None to the children component of the fs_spinner, which removes the spinner from the screen.
Hope this helps!

What is the flow of Plotly dash program (python)

Actually I am new with python dash library and learning Plotly dash. Where I am bit confused that how this program flows when we run it?
(Like in java program first main method runs and then functions one by one in main method gets run...)
Can anyone just explain or will share the flow diagram?
The Plotly Dash workflow -
a) First create an app.
app = dash.Dash(__name__, requests_pathname_prefix = '/app',
external_stylesheets = external_stylesheet)
b) Secondly create the app layout.
app.layout = html.Div([
html.Div([....])
])
c) Thirdly create the callbacks
#app.callback(Output(component_id = 'id' , component_property = 'data'),
[Input(component_id = 'id', component_property = 'value'])
d) Fourthly, run the app.
app.run_server(debug = True)

dash doesn't refresh pages

I'm trying to test the refresh page logic.
I read the manual:
https://dash.plotly.com/live-updates
And wrote this simple code:
import datetime
import dash
import dash_html_components as html
def get_time():
print("get time...")
return datetime.datetime.now()
def serve_layout():
return html.H1('The time is: ' + str(get_time()))
if __name__ == '__main__':
app = dash.Dash()
app.layout = serve_layout()
app.run_server(debug=True)
I expected to see that every page refresh (F5) I will see the log "get time...",
But I see this log only on startup and not on every refresh.
What am I missing ?
I want to wrote a logic that every page refresh (F5) the function serve_layout (and get_time) will be called.
How can I do it ?
It looks like you are assigning the rendered layout instead of a function, which is needed to update on page refresh. Hence if you replace the line
app.layout = serve_layout()
with
app.layout = serve_layout
it should work as expected.

Update application state outside of callback in plotly dash

I'm writing a plotly Dash application where I don't initially have database access, so I need to wait for the database connection before I can set the initial application state.
Thus, I want to run a function that will set the application state later on, but the only way to set state seems to be with #app.callback() decorators, but the problem is they require a property or state variable to watch before firing, but in my case I'm not watching part of the Dash app, I'm watching something external.
How can I do this in Dash?
For example:
app = Dash(routes_pathname_prefix='/dash/trend/')
app.layout = html.Div(children=[
dcc.Dropdown(
options=get_field_options(),
id='field_select',
multi=True,
)
])
#app.callback(
dash.dependencies.Output('field_select', 'options'),
[
# What do I put here as an input??
]
)
def update_fields(href):
return get_field_options()
You can use plotly dash store component to keep some data needed for event.
dcc.Store(id='local', storage_type='local'),
Dash Store component
Use a hidden html.Div() to store your information. This can be empty:
html.Div(id='application-state', style={'display': 'none'})
So your code should look like this:
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
app = Dash(routes_pathname_prefix='/dash/trend/')
app.layout = html.Div(children=[
dcc.Dropdown(
options=get_field_options(),
id='field_select',
multi=True,
),
html.Div(id='application-state', style={'display': 'none'})
])
#app.callback(
[Output('field_select', 'options')],
[Input('application-state', 'children')])
def update_fields(href):
if href =! None:
return get_field_options()
else:
return []
Your external part should update the respective hidden div. You can change this to any other component that is able to store the information you want to transfer to the dash visualization. You find the best sources and tricks for this problem domain here.
The if else part for returning a valid object is a bit tricky. Please let me know if there is a callback output error like Expected 1 output but received None or something similar.

Categories