How to write Dash callbacks to only update the unique values of multiple dropdowns from querying a database where persistence_type='session'

I’m looking to update the unique values that appear in a dropdown with persistence_type = 'session' while keeping all plots on the page containing persistence_type='memory'. I want it to be flexible enough to control across different pages, so on page1:

import plotly
import plotly.express as px

import dash
from dash import Dash, callback, html, dcc, dash_table, Input, Output, State, MATCH, ALL, dash_table
import dash_bootstrap_components as dbc


@callback(
    [Output('dropdown-data-store', 'data')],
    [Input('query-dropdown-data', 'data')]
)
def query_dropdown_options():
    dropdown_options = {
        'dropdown1': db.run_sql('select distinct(colA) from tableA')['colA'].tolist(),
        'dropdown2': db.run_sql('select distinct(colB) from tableB')['colB'].tolist()
    }
    return dropdown_options


@callback(
    [Output('dropdown1', 'options'), Output('dropdown2', 'options')],
    [Input('dropdown-data-store', 'data')]
)
def update_dropdown_options(dropdown_options):
    data_store = [
        [{'label': item, 'value': item} for item in dropdown_options['colA']],
        [{'label': item, 'value': item} for item in dropdown_options['colB']]
    ]

    return data_store


layout = dbc.Container([

    dbc.Row([dbc.Col([html.H5('Filters')])]),

    ### Data Store ###

    dcc.Store(id='dropdown-data-store', storage_type='session', data=[]),

    # dropdown1
    dbc.Col([dcc.Dropdown(id='dropdown1',
                          options=[],
                          value='',
                          placeholder='dropdown1',
                          # persistence=True,
                          # persistence_type='session',
                          multi=True)]),

    # dropdown2
    dbc.Col([dcc.Dropdown(id='dropdown2',
                          options=[],
                          value='',
                          placeholder='dropdown2',
                          # persistence=True,
                          # persistence_type='session',
                          multi=True)]),


    ###### Plots ######

    dbc.Row([
        dbc.Col(dcc.Graph(id='myplot'))
    ])
])

I have also tried defining the callback a few other ways like the one below

@callback(
    [Output('dropdown1', 'options'), Output('dropdown2', 'options')],
    [Input('dropdown-data-store', 'data'),
     State('dropdown1', 'value'), State('dropdown2', 'value')]
)
def update_dropdown_options(dropdown_options, dropdown1, dropdown2):
    dropdown_options = {
        'dropdown1': db.run_sql('select distinct(colA) from tableA')['colA'].tolist(),
        'dropdown2': db.run_sql('select distinct(colB) from tableB')['colB'].tolist()
    }

    data_store = [
        [{'label': item, 'value': item} for item in dropdown_options['dropdown1']],
        [{'label': item, 'value': item} for item in dropdown_options['dropdown2']]
    ]

    return data_store

The problem with the first callback example is that when it is set to Input, then after every click the dropdown re-hits the database (undesirable). When I change Input to State the first callback example doesn’t update the dropdowns at all.

The problem with the second callback example is the dropdown still updates after every page refresh even though persistence_type is set to ‘session’ or ‘local’

Hi, maybe I am wrong, but isn’t there something like that in the docs?

Do you want the first callback to run after the page loads? Add an invisible button style = {'display':'none'} that should trigger the callback on page load and probably never again, and make “query…data” a state.

I hope this could help!