add callbacks dynamically
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Python
- Estrellas
- 24.4k
- Forks
- 2.3k
- Merge medio
- 2 d 7 h
- PR fusionados (30 d)
- 13
Descripción
Hi!
this is somewhat of a mixture of a feature request and a bug report. here is my example:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import json
import os
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions=True
try:
os.remove('cities.json')
except OSError:
pass
def make_cb(city):
@app.callback(Output('%s-pushed' % city, 'children'),
[Input('%s-but' % city, 'n_clicks')],
[State('%s-but' % city, 'children')])
def fing(nc,cval):
if nc:
return cval
return ''
def get_layout():
try:
cities = json.load(open('cities.json'))
except FileNotFoundError:
cities = []
return html.Div([
dcc.Input(id='input-1', type='text', value='Montréal'),
html.Button(id='submit-button', n_clicks=0, children='Submit'),
html.Div(id='pushed-city'),
html.Div([html.Div([html.Button(c,id='%s-but' % c),
html.Div(id='%s-pushed' % c)])
for c in cities],id='output-state')
])
app.layout = get_layout
@app.callback(Output('output-state', 'children'),
[Input('submit-button', 'n_clicks')],
[State('input-1', 'value')])
def update_output(n_clicks, input1):
try:
cities = set(json.load(open('cities.json')))
except FileNotFoundError:
cities = set()
if input1 not in cities and input1 is not None:
cities.add(input1)
cities = list(cities)
json.dump(cities,open('cities.json','w'))
make_cb(input1)
print(app.callback_map)
return [html.Div([html.Button(c,id='%s-but' % c),
html.Div(id='%s-pushed' % c)])
for c in cities]
if __name__ == '__main__':
app.run_server(debug=True)
this is a simple app based on the documentation, that allows the user to add interactive elements, with some caching. There are two issues. The first one I don't understand, the second one I do.
-
If I click the submit button, to add a city, everything appears fine, the
print(app.callback_map)line shows me that the callback has been registered, i can see everything in the browser, however the callback does not become active, until I refresh the browser. -
If I use a proper server like gunicorn not the flask development server, with parallel processes, the callback_map dictionary is not shared, so the whole thing breaks down, and the callbacks basically don't work.
Now, I'm quite sure that 1, has some easy explanation that I'm just a little too tired to figure out, I wrote this whole thing because of 2,
I also hacked together a solution for myself for the second one, that allows for declaring the callback map as a shared key-value store, using redis. If anyone's interested, I can post a PR. As far as i can see, only __iter__, __getitem__, __setitem__ and items() are utilized from the callback_map.
I looked through #577 #475 #373 this and this. Based on these, creating a shared key-value store for the callbacks is a well isolated issue that fits the main arch of these topics.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Empieza por rastrear cómo Dash registra y consume app.callback_map durante el despacho de callbacks, usando como reproducción el ejemplo dynamic-callback del issue. Investiga las implicaciones de almacenar metadatos de callbacks en un almacén de clave-valor compartido respaldado por Redis entre procesos worker. Se considera terminado cuando los callbacks añadidos dinámicamente funcionan sin actualizar el navegador y siguen disponibles con múltiples procesos del servidor.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python, redis
- Área
- backend, distributed-systems
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 25/100