Hey everyone,
I’ve been learning Dash over the past few days and am going through the tutorial. As I’ve done more and more callbacks, I realized app.py file was getting way too big. I’m afraid that in a real-case scenario, having the callbacks within app.py file might be a mess, so I’d like to have the following architecture:
app.py that contains the main app and its layout
callbacks1.py that contains some callback functions
callbacks2.py same thing
I’ve ALMOST managed to make it work. Here is my code:
app3.py
# -*- coding: utf-8 -*-
################################################################################
###
### IMPORTS
###
################################################################################
import os
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
################################################################################
###
### SETUP
###
################################################################################
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
app = dash.Dash(__name__)
df3 = pd.read_csv('data/test_data_3.csv', sep='|')
################################################################################
###
### LAYOUT
###
################################################################################
app.layout = html.Div([
html.Div([
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
id='year-slider',
min=df3['year'].min(),
max=df3['year'].max(),
value=df3['year'].max(), # Base value
marks={str(year): str(year) for year in df3['year'].unique()},
),
]),
])
################################################################################
###
### CALLBACKS
###
################################################################################
import cbs3
################################################################################
###
### RUN
###
################################################################################
if __name__ == '__main__':
app.run_server(debug=True)
cbs3.py
import plotly.graph_objs as go
import dash.dependencies as dd
from app3 import app, df3
@app.callback(
dd.Output('graph-with-slider', 'figure'),
[dd.Input('year-slider', 'value')]
)
def update_with_slider(selected_year):
""" Update the figure property of our graph based on the slider value, everytime it is modified """
filtered_df = df3[df3.year == selected_year]
traces = []
for i in filtered_df.continent.unique():
df_by_continent = filtered_df[filtered_df.continent == i]
traces.append(go.Scatter(
x=df_by_continent.gdpPercap,
y=df_by_continent.lifeExp,
text=df_by_continent.country,
mode='markers',
opacity=0.7,
marker={
'size':15,
'line': {'width':0.5, 'color': 'white'}
},
name=i,
))
# We return a dict that basically is the property for the dcc.Graph() element.
return {
'data': traces,
'layout': go.Layout(
xaxis={'type': 'log', 'title': 'GPD Per Capita',},
yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
legend={'x': 0, 'y': 1},
hovermode='closest',
),
}
The weird thing is that: if I change “import cbs3” into “from cbs3 import *”, it works. If I leave "import cbs3’, it doesn’t work. I’d like to understand why and be able to fix it, as I know using “import *” is not a good idea.
Any help would be greatly appreciated.
Thanks