Use linked Select Widgets to filter on dataset

Hey, I’m a newbie using Bokeh for months on my projects, and just found this community recently. I’m having a question need your expertise guidance.
Generally, I want to build a bokeh serve webpage, where there are 3 main select widgets to perform data selection and filtering: The 1st select widget lets user to choose which raw file to load as the working dataframe, 2nd one reads the header row of this df, list down the column names with “categorical” values, user can choose one column name here, 3rd widget lists down all unique values from the selected column for user to choose which value to be filtered.
Basically it’s a query like "SELECT * from file (select1.value) WHERE column (select2.value) == choice (select3.value).
Finally the filtered dataframe will be fed to next steps for manipulation and visualization.

My codes are as below:

job_lists = os.listdir('..\input_files')

def load_raw_file(attr, old, new):
    df_raw = pd.read_csv('..\input_files' + '\\' + select_jobdata.value + '\\data.csv')
    return df_raw

def update_data(attr, old, new):
    df_raw = load_raw_file()
    raw_columns = df_raw.columns
    categorical_cols = [x for x in raw_columns if df_raw[x].dtype == object]
    select_column.options = categorical_cols
    choice = select_column.value
    select_value.value = list(df_raw[choice].unique())[0]
    select_value.options = list(df_raw[choice].unique())
    layout.children[1] = select_column
    layout.children[2] = select_value

select_jobdata = Select(title = 'JobID:', value = job_lists[0],  options = list(job_lists))
select_jobdata.on_change('value', load_raw_file)

select_column = Select(title = 'Column:', value = 'None')
select_column.on_change('value', update_data)

select_value = Select(title = 'Filter:')

layout = column(select_jobdata, select_column, select_value)
curdoc().add_root(layout)

When I run this code with bokeh serve command, the 3 widgets show up on the webpage, but only 1st widget has valid dropdown values, other 2 are blank. How should I correct the code to make it work as expected?
p.s: I need to pass the df_raw to other functions for plotting, should I “return” it at the end of “update_data” function?

Appreciate in advance.

Only the first Select widget has a value and list property assigned. Even if the user hasn’t made a selection, those properties need to be initialized (probably with a dummy value) for the widgets to display a list. My preference is to create a ‘data’ class which then all the different methods or callbacks can access and update, something like…

class select_data:
    def __init__(self):
        self.raw_data = None
        self.job_lists = list(os.listdir('..\input_files'))
        self.col_options = [None]
        self.val_options = [None]

selection = select_data()        

def load_raw_file(attr, old, new):
    selection.raw_data = pd.read_csv('..\input_files' + '\\' + select_jobdata.value + '\\data.csv')

def update_data(attr, old, new):
    if selection.raw_data is None:
        print('Make a file selection first.')
    else:
        raw_columns = selection.raw_data.columns
        categorical_cols = [x for x in raw_columns if selection.raw_data[x].dtype == object]
        select_column.options = categorical_cols
        choice = select_column.value
        select_value.value = list(selection.raw_data[choice].unique())[0]
        select_value.options = list(selection.raw_data[choice].unique())
        layout.children[1] = select_column
        layout.children[2] = select_value

select_jobdata = Select(title = 'JobID:', value = selection.job_lists[0],  options = selection.job_lists)
select_jobdata.on_change('value', load_raw_file)

select_column = Select(title = 'Column:', value = selection.col_options[0], options = selection.col_options)
select_column.on_change('value', update_data)

select_value = Select(title = 'Filter:', value = selection.val_options[0], options = selection.val_options)

layout = column(select_jobdata, select_column, select_value)
curdoc().add_root(layout)