gpt4 book ai didi

python - 服务于 Flask 服务器的 Dash 应用程序内部服务器错误 : A name collision occurred between blueprints

转载 作者:行者123 更新时间:2023-12-05 07:08:09 26 4
gpt4 key购买 nike

我正在 Flask 服务器中使用 Dash 应用程序。

这就是我实例化 Flask 服务器的方式:

from flask import Flask, redirect
server = Flask(__name__, template_folder="../frontend/templates",
instance_relative_config=True)

这是 create_dash_app 函数:

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

在我的一个服务器路由中,我有以下内容:

@server.route('/filter')
def filter_stuff():

<some code>

create_dash_app()
redirect("/dash")

重点是,对于我的用例,用户可能希望查看 dash 应用程序,返回到过滤器路由,应用一些过滤器并检查 dash 应用程序中的更改。不幸的是,当我这样做时,我得到以下信息:

> 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.

鉴于我对 Flask 和 Dash 的经验不多,我想我缺少的是一些微不足道的东西。如果您可能需要其他信息,请告诉我。

编辑:我找到了一个让我感到羞愧的解决方法第二次编辑:包括一个回调示例

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

如您所见,我每次都使用计数器重定向到新页面。我想知道是否有人会死于阅读此文。

谢谢

最佳答案

虽然 Dash 应用程序可以动态实例化,但根据我的经验,这是一种应该避免的设计模式。关于这个问题中针对的具体用例,我会考虑两个主要途径,

将过滤器与 Dash 应用集成

最简单和连贯的解决方案是将过滤器作为 Dash 应用程序本身的一部分。使用这种方法,可以通过将过滤器值作为 State 参数传递给页面呈现回调来将过滤器应用于其他页面。它们可以直接传递(如果没有太多过滤器)或通过例如聚合一个 Store 组件。这是一个代码片段来说明这个概念,

@app.callback(Output("store", "data"), [Input("filter{}".format(i), "value") for i in range(100)])
def aggregate_filters(*args):
return list(args)


@app.callback(Output("page", "children"), [Input(...)], [State("store", "data")])
def render_page(*args, filters):
...

将过滤器选择传递给 Dash 应用

如果无法将过滤器页面本身移植到 Dash,您可以序列化过滤器选择并将它们传递给 Dash 应用程序。可能是例如通过 URL(如果没有太多选择)或 session 变量。这是后者的草图,

from flask import session, redirect

...

@server.route('/filter')
def filter_stuff():
# This assignment might happen from JavaScript depending on you app structure
session["filters"] = ...
redirect(dash_address)

...

@app.callback(Output("page", "children"), [Input(...)])
def render_page(*args, filters):
filters = session["filters"]
...

此方法的其他变体包括保存选择服务器端(例如,在文件或内存缓存中,如 Redis),由一个键标识,例如一个 uuid,然后通过 URL 传递给 Dash 应用程序。

关于您目前使用的 hack,除了不太漂亮之外,我担心它会耗尽服务器资源,因为每次过滤器选择更改时您都在有效地创建一个新的 Dash 应用程序。

关于python - 服务于 Flask 服务器的 Dash 应用程序内部服务器错误 : A name collision occurred between blueprints,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61921054/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com