python - python dash 回调动态生成的搜索结果。一定有更好的方法
问题描述
我有一个破折号应用程序,它获取短文本列表和一些关于它们的元数据作为输入。我在一个填充了数据的无序列表中显示这些文本。现在我想为我的所有列表元素设置一个通用回调,以便在单击它们时填充详细视图并运行相似性算法。此外,用户应该能够添加和删除类别(然后将句子放入类别中,但这还没有实现)。这是到目前为止的代码。它使用破折号的模式匹配回调。首先,它非常慢,其次,我很确定必须有更好的方法来实现这种行为。
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, MATCH, ALL
from dash_html_components.Button import Button
import datasets
import html_generators
import re
app = dash.Dash(__name__)
sentences, embeddings = datasets.dataset_from_csv('sentences')
categories = set(sentence['category'] for sentence in sentences if sentence['category'])
app.layout = html.Div([
html.Div(
className="app-header",
children=[
html.Div('Plotly Dash', className="app-header--title")
]
),
html.Div(
className="arg-list-pane",
children=[
html.Div(className="arg-list-box", children=[
html.Div('Header', className="arg-list-header"),
html.Ul(children=[
html.Div(
sentence['sentence'],
id={'type': 'argument-container', 'index': sentence['id']},
className="arg-container") for sentence in sentences]
)]
),
html.Div('Argument Details', id="argument-detail-box")
]
),
html.Div(
className="category-pane",
children=[
html.Div(className="category-box", children=[
html.Div(
className="category-header",
children=[
dcc.Input(id='cat-input', value='Add Category..', type='text'),
html.Button(id='submit-cat-button', n_clicks=0, children='Add')
]),
html.Ul(
id='cat_list',
children=[
html.Div(category, {'type': 'category-item', 'index': index},
className="category-container")
for index, category in enumerate(categories)
])
]
),
html.Div("algorithm output here", id='algo-box')
]
)
])
@app.callback(
Output('cat_list', 'children'),
Input('submit-cat-button', 'n_clicks'),
Input("cat-input", "n_submit"),
Input({'type': 'category-remove-btn', 'index': ALL}, 'n_clicks'),
State('cat-input', 'value'),
State('cat_list', 'children')
)
def add_category(n_clicks, n_submit, remove_click, cat_input, children):
"""Handle Category input.
Data from the input box can be submitted with enter and button click. If
that happens, a new category will be created if it doesn't exist yet.
If the remove button of a category is presesd, the corresponding list
element will be deleted.
"""
if n_clicks or n_submit:
trigger_id = dash.callback_context.triggered[0]['prop_id']
if trigger_id.startswith('submit-cat-button') or trigger_id.startswith('cat-input'):
already_there = False
for category in children:
if cat_input in category['props']['children']:
already_there = True
if not already_there:
new_cat = html.Li(
children= [
cat_input,
html.Button(
'remove',
id={'type': 'category-remove-btn', 'index': len(children)})
],
id={'type': 'category-item', 'index': len(children)},
className="category-container")
children.append(new_cat)
else:
button_id = int(re.findall('\d+', trigger_id)[0])
for child in children:
if child['props']['children'][1]['props']['id']['index'] == button_id:
children.remove(child)
return children
@app.callback(
Output('argument-detail-box', 'children'),
Output('algo-box', 'children'),
Input({'type': 'argument-container', 'index': ALL}, 'n_clicks')
)
def handle_arg_click(n_clicks):
"""handle click on a list item.
When a list item is clicked, the n_clicks property will update, the callback
will be triggered and the responsible list element will be stored in
`dash.callable_context.triggered`. From that, the index/id of the sentence
is known. With that information, the algorithm can be fed and the info box
can be changed.
"""
if not dash.callback_context.triggered[0]['value']:
raise dash.exceptions.PreventUpdate
sentence_id = int(re.findall('(\d+)',dash.callback_context.triggered[0]['prop_id'])[0])
sentence_data = sentences[sentence_id]
details_table = html_generators.create_details_table(sentence_data, header='argument details')
return details_table, 'Similarity Score list here'
if __name__ == '__main__':
app.run_server(debug=True)
从模式匹配回调中获取句子 ID 非常简单,但使用正则表达式查找正确的 ID 对我来说似乎有点不靠谱。此外,这就是应用程序运行缓慢的原因,因为我大约有 1200 个句子都在列表中,并且模式匹配回调要么返回所有数据,要么您必须指定匹配的输出。由于我有一个通用的输出视图,我必须根据 docs在模式匹配回调中匹配所有内容。
您还可以看到我使用删除按钮处理动态创建类别的方式,并查看嵌套的 dict/list 结构以找出在按下删除按钮时要删除的子元素。我无法想象这是最好的方法。
我是编写此类 Web 界面的新手,所以也许我错过了一个核心概念,它甚至没有在 dash 文档中详细说明。我只是有一种预感,这不是为用户或数据生成的 html 元素(如列表项)实现回调的正确方法。
您将如何实现这样的努力 - 用户单击(动态创建)列表元素和填充详细信息视图,所以非常基本的东西 - 在 python dash 中?
解决方案
推荐阅读
- c# - 在模式对话框中使用搜索框,如何在不重新加载整个页面的情况下显示搜索结果?
- android - onNewToken() 未被超类 FirebaseMessagingService 覆盖
- json - 在 bash 中的特定 JSON 字段中查找最高值
- sql-server-2008-r2 - VS2019 安装项目构建错误(SQL Server 2008 R2 SP1 Management Studio)
- java - 如何转换 HTML
- post - 如何将超过1GB的文件上传到godaddy
- ubuntu - makefile 不在 raspbian 工作,但在 ubuntu 工作
- javascript - 使用 Intl.DateTimeFormat 和 en-US 区域设置,Safari 中的日期显示为 1
- sql - 如何使用 T-SQL 组合多个不同长度的父子关系?
- html - Flexbox:元素折叠——最好的方法?