Python 为Flask服务器提供服务的Dash应用程序出现内部服务器错误:蓝图之间发生名称冲突

Python 为Flask服务器提供服务的Dash应用程序出现内部服务器错误:蓝图之间发生名称冲突,python,flask,web-applications,plotly-dash,Python,Flask,Web Applications,Plotly Dash,我正在使用Flask服务器中的Dash应用程序 这是我如何实例化Flask服务器的: from flask import Flask, redirect server = Flask(__name__, template_folder="../frontend/templates", instance_relative_config=True) 这是“创建短跑应用程序”功能: import dash def create_dash_app(server):

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

这是我如何实例化Flask服务器的:

from flask import Flask, redirect
server = Flask(__name__, template_folder="../frontend/templates",
               instance_relative_config=True)
这是“创建短跑应用程序”功能:

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")
> 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.
@server.route(“/filter”)
def filter_stuff():
创建_dash_app()
重定向(“/dash”)
关键是,对于我的用例,用户可能希望看到dash应用程序,返回过滤器路径,应用一些过滤器并检查dash应用程序中的变化。 不幸的是,当我这样做时,我得到了以下信息:

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

    <some code>

    create_dash_app()
    redirect("/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.
>AssertionError:蓝图之间发生名称冲突
>及
> . 双方都有共同的利益
>同名“\u dash\u dash\u资产”。动态创建的蓝图
>需要唯一的名称。
考虑到我在烧瓶和短跑方面的一点经验,我想我遗漏了一些琐碎的东西。请告诉我您是否需要其他信息

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

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
从烧瓶导入烧瓶,重定向
从多处理导入值
计数器=值('i',0)
server=Flask(_name__,template_folder=“../frontend/templates”,
实例\相对\配置=真)
@server.route(“/filter”)
def filter_stuff():
带计数器。获取锁定()
计数器值+=1
out=计数器值
破折号地址=“/dash”+str(out)+“/”
创建应用程序(服务器、地址、节点、边缘)
重定向(破折号地址)
导入破折号
从dash_核心组件导入*
从dash.dependencies导入输入,输出
def创建破折号应用程序(服务器、破折号地址、节点、边缘):
破折号应用程序=破折号(
__姓名,
服务器=服务器,
url\u base\u pathname=dash\u地址,
外部_样式表=['https://codepen.io/chriddyp/pen/bWLwgP.css']
)
dash_app.config['suppress_callback_exceptions']=True
dash_app.layout=html.Div([
细胞景观(
id='cytoscape\u net',
元素=节点\细胞+边缘\细胞,
zoomingEnabled=True,
缩放=0.8,
布局={'name':'klay'},
样式={'width':'80%,'height':'700px','float':'left'},
样式表=我的样式表
),
dcc.选项卡([
dcc.Tab(label='Dettaglio Interazioni',style=Tab\u style,selected\u style=Tab\u selected\u style,children=[
dash_table.DataTable(
id='edge-table',
列=[],
样式标题={
“背景色”:“rgb(230230230)”,
“fontWeight”:“bold”
},
修复了_行={'headers':True},
style_data={'whiteSpace':'normal',
“高度”:“自动”,
“线宽”:“15px”},
样式\数据\条件=[
{
'if':{'row_index':'odd'},
“背景色”:“rgb(248248248248)”
},
{
'if':{'column_id':'Info'},
“textAlign”:“右”
}
],
花式细胞={
“高度”:“自动”,
“minWidth”:“180px”,“width”:“180px”,“maxWidth”:“180px”,
“空白”:“正常”,
“字体大小”:14
},
样式表={'width':'50%,
“溢出”:“自动”,
'overflowX':'auto'},
数据=[])
])
init_回调(dash_应用程序)
返回dash_应用程序服务器
def init_回调(应用程序):
@app.callback([Output('edge-table','data'),
输出('edge-table','columns')],
[输入('cytoscape_net','tapEdgeData'))
def populateEdgeTable(数据):
json_data=json.loads(json.dumps(data,indent=2))
如果数据为无:
返回[],[]
dict_data=dict(json_数据)
dict_data_1={your_key.replace(“_1”,”):dict_data[your_key]作为您的_key in
[j表示dict_data.keys()中的j,如果j中的“_1”+[“tipo_interazione”]}
dict_data_2={your_key.replace(“_2”,”):dict_data[your_key]用于您的_key in
[j表示dict_data.keys()中的j,如果j中的“_2”+[“tipo_interazione”]}
列=[{'name':'Info','id':'Info'},
{'name':'Source','id':'Source'},
{'name':'Target','id':'Target'}]
返回pd.DataFrame({'Info':list(dict_data_1.keys()),
“源”:列表(dict_data_1.values()),
“目标”:列表(dict_data_2.values())}.to_dict(orient='records'),列
正如你所看到的,我每次都用一个计数器重定向到一个新的页面。我想知道是否有人会在读这篇文章时死去

谢谢

< P>但DASH应用程序可以动态实例化,在我的经验中,这是一个应该避免的设计模式。关于这个问题的具体用例,我会考虑两个主要途径,

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

@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,则可以序列化筛选器