I'm working with a Dash App inside a Flask Server.
This is how I instantiate the Flask Server:
from flask import Flask, redirect
server = Flask(__name__, template_folder="../frontend/templates",
instance_relative_config=True)
This is the create_dash_app function:
import dash
def create_dash_app(server):
dash_app = dash.Dash(
__name__,
server=server,
url_base_pathname='/dash/',
external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css']
)
dash_app.config['suppress_callback_exceptions'] = True
dash_app.layout = html.H3("Lorem ipsum... ")
return dash_app.server
At one of my server routes I have the following:
@server.route('/filter')
def filter_stuff():
<some code>
create_dash_app()
redirect("/dash")
The point is that for my use case a user may want to see the dash app, go back to the filter route, apply some filters and check the changings in the dash app. Unfortunately, when I do that I get the following:
> AssertionError: A name collision occurred between blueprints
> <flask.blueprints.Blueprint object at 0x11905bcd0> and
> <flask.blueprints.Blueprint object at 0x118acbad0>. Both share the
> same name "_dash_dash_assets". Blueprints that are created on the fly
> need unique names.
Given my little experience with Flask and Dash I guess it's something trivial that I'm missing. Please tell me if there is additional info you may need.
EDIT: I've found a workaround which I'm ashamed of 2nd EDIT: included a callback example
from flask import Flask, redirect
from multiprocessing import Value
counter = Value('i', 0)
server = Flask(__name__, template_folder="../frontend/templates",
instance_relative_config=True)
@server.route('/filter')
def filter_stuff():
with counter.get_lock():
counter.value += 1
out = counter.value
<some code>
dash_address = "/dash"+str(out)+"/"
create_dash_app(server, dash_address, nodes_cyto, edges_cyto)
redirect(dash_address)
import dash
from dash_core_components import *
from dash.dependencies import Input, Output
def create_dash_app(server, dash_address, nodes_cyto, edges_cyto):
dash_app = dash.Dash(
__name__,
server=server,
url_base_pathname=dash_address,
external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css']
)
dash_app.config['suppress_callback_exceptions'] = True
dash_app.layout = html.Div([
cyto.Cytoscape(
id='cytoscape_net',
elements=nodes_cyto + edges_cyto,
zoomingEnabled=True,
zoom=0.8,
layout={'name': 'klay'},
style={'width': '80%', 'height': '700px', 'float': 'left'},
stylesheet=my_stylesheet
),
dcc.Tabs([
dcc.Tab(label='Dettaglio Interazioni', style=tab_style, selected_style=tab_selected_style, children=[
dash_table.DataTable(
id='edge-table',
columns=[],
style_header={
'backgroundColor': 'rgb(230, 230, 230)',
'fontWeight': 'bold'
},
fixed_rows={'headers': True},
style_data = {'whiteSpace': 'normal',
'height': 'auto',
'lineHeight': '15px'},
style_data_conditional=[
{
'if': {'row_index': 'odd'},
'backgroundColor': 'rgb(248, 248, 248)'
},
{
'if': {'column_id': 'Info'},
'textAlign': 'right'
}
],
style_cell={
'height': 'auto',
'minWidth': '180px', 'width': '180px', 'maxWidth': '180px',
'whiteSpace': 'normal',
'fontSize':14
},
style_table={'width': '50%',
'overflowY': 'auto',
'overflowX': 'auto'},
data=[])
])
init_callbacks(dash_app)
return dash_app.server
def init_callbacks(app):
@app.callback([Output('edge-table', 'data'),
Output('edge-table', 'columns')],
[Input('cytoscape_net', 'tapEdgeData')])
def populateEdgeTable(data):
json_data = json.loads(json.dumps(data, indent=2))
if data is None:
return [], []
dict_data = dict(json_data)
dict_data_1 = {your_key.replace("_1", ""): dict_data[your_key] for your_key in
[j for j in dict_data.keys() if "_1" in j] + ["tipo_interazione"]}
dict_data_2 = {your_key.replace("_2", ""): dict_data[your_key] for your_key in
[j for j in dict_data.keys() if "_2" in j] + ["tipo_interazione"]}
columns = [{'name': 'Info', 'id': 'Info'},
{'name': 'Source', 'id': 'Source'},
{'name': 'Target', 'id': 'Target'}]
return pd.DataFrame({'Info': list(dict_data_1.keys()),
'Source': list(dict_data_1.values()),
'Target': list(dict_data_2.values())}).to_dict(orient='records'), columns
As you can see I'm using a counter to redirect to a new page each time. I wonder if some people might die reading this.
Thank you