Hi, I recently updated dash version to 3.1.1 from 2.. In dash 2. there is a arguments like session check and args check to limit the creation of multiple files for the same serverside output. is there a way to do that in dash 3.*.
Tried using Dash Extension enriched output as well but still doesnt seem to work.
Attached a sample code where this behaviour can be replicated
import os
import random
from datetime import datetime, timedelta
import numpy as np
import pandas as pd
import plotly.graph_objs as go
import dash
from dash import dcc, html, Input, callback
from dash_extensions.enrich import (
Dash,
Output,
Serverside,
EnrichedOutput,
FileSystemBackend,
ServersideOutputTransform,
DashProxy
)
# Create FileSystemStore backend with threshold
dash_backend = FileSystemBackend(cache_dir="dash_file_system_store")
app = DashProxy(__name__, transforms=[ServersideOutputTransform(backends = [dash_backend])])
def generate_historical_data(hours=6):
end = datetime.now()
mins = [end - timedelta(minutes=i) for i in range(hours * 60)]
return [
{
'timestamp': ts.isoformat(),
'random_value': random.uniform(0, 100),
'trend_value': 50 + 20 * np.sin((ts.hour + ts.minute/60) * np.pi / 12)
+ random.gauss(0, 5)
}
for ts in reversed(mins)
]
app.layout = html.Div([
html.H1("Random Number Dashboard"),
html.Div([
html.Label("Update Interval (seconds):"),
dcc.Slider(id='interval-slider', min=1, max=10, step=1, value=2,
marks={i: str(i) for i in range(1, 11)})
]),
html.Div([
html.Button('Generate Historical Data', id='generate-data-btn'),
html.Button('Clear Data', id='clear-data-btn')
]),
html.Div(html.Span(id='data-status')),
dcc.Store(id='live-data-store'),
dcc.Store(id='historical-data-store'),
dcc.Interval(id='interval-component', interval=2000, n_intervals=0),
dcc.Graph(id='live-graph'),
html.Div([
html.Div([html.H3("Current"), html.H2(id='current-value-kpi')]),
html.Div([html.H3("Average"), html.H2(id='average-kpi')]),
html.Div([html.H3("Count"), html.H2(id='count-kpi')])
], style={'display': 'flex', 'justifyContent': 'space-around'})
])
@app.callback(
Output('interval-component', 'interval'),
Input('interval-slider', 'value'))
def update_interval(val):
return val * 1000
@app.callback(
EnrichedOutput('historical-data-store', 'data', arg_check= False, session_check= True),
Output('data-status', 'children'),
Input('generate-data-btn', 'n_clicks'),
Input('clear-data-btn', 'n_clicks'),
memoize = True,
prevent_initial_call=True)
def manage_history(gen_clicks, clear_clicks):
ctx = dash.callback_context
trig = ctx.triggered[0]['prop_id']
if 'generate' in trig:
data = generate_historical_data(hours=6)
return Serverside(data), f"Generated {len(data):,} points"
if 'clear' in trig:
return Serverside([],), "All data cleared"
return dash.no_update, ""
@app.callback(
EnrichedOutput('live-data-store', 'data', arg_check= False, session_check=True),
Input('interval-component', 'n_intervals'),
memoize = True,)
def update_live(n):
now = datetime.now()
times = [now - timedelta(seconds=30 * i) for i in range(30, 0, -1)]
return Serverside([
{
'timestamp': ts.isoformat(),
'random_value': random.uniform(0, 100),
'trend_value': 50 + 20 * np.sin((ts.hour + ts.minute/60) * np.pi / 12)
+ random.gauss(0, 5)
}
for ts in times
],)
@app.callback(
Output('live-graph', 'figure'),
Input('live-data-store', 'data'),
Input('historical-data-store', 'data'))
def draw_graph(live, hist):
df = pd.DataFrame(hist) if hist else pd.DataFrame(live or [])
if df.empty:
return go.Figure().update_layout(title="No Data Available")
df['timestamp'] = pd.to_datetime(df['timestamp'])
df = df.sort_values('timestamp')
fig = go.Figure()
fig.add_trace(go.Scatter(x=df['timestamp'], y=df['random_value'], mode='lines+markers'))
fig.add_trace(go.Scatter(x=df['timestamp'], y=df['trend_value'], mode='lines'))
fig.update_layout(title="Random Numbers", hovermode='x unified')
return fig
@app.callback(
Output('current-value-kpi', 'children'),
Output('average-kpi', 'children'),
Output('count-kpi', 'children'),
Input('live-data-store', 'data'),
Input('historical-data-store', 'data'))
def update_kpis(live, hist):
df = pd.DataFrame(hist or live or [])
if df.empty:
return "N/A", "N/A", "0"
current = f"{df.iloc[-1]['random_value']:.1f}"
average = f"{df['random_value'].tail(10).mean():.1f}"
count = f"{len(df):,}"
return current, average, count
if __name__ == "__main__":
app.run(debug=True)
version of dash and related libraries
dash==3.1.1
dash-bootstrap-components==2.0.2
dash-core-components==2.0.0
dash-extensions==2.0.4
dash-html-components==2.0.0
dash-table==5.0.0
dash_ag_grid==31.3.1
dash_daq==0.6.0
dash_mantine_components==1.2.0
Thanks in Advance