I have the following pseudocode that I’m trying to improve:
# define global (sidebar) inputs
start_date = pn.widgets.DatePicker()
end_date = pn.widgets.DatePicker()
filter_col = pn.widgets.Select()
filter_values = pn.widgets.MultiSelect()
# create template and add global inputs that all get_data + render_data use
template = pn.template.BootstrapTemplate(
title="My Dashboard",
sidebar=[start_date, end_date, filter_col, filter_values],
)
# define 1 (of many) get_data + render_data pairs
# this one has an additional specific input
get_data1_specific_input = pn.widgets.Number()
@pn.depends(start_date, end_date, filter_col, get_data1_specific_input)
def get_data1(foo):
... # slow expensive database fetch
@pn.depends(filter_values)
def render_data1():
# not sure... do i put get_data() here?
# this is where my paradigm breaks down and I'm looking for suggestions
# I don't want to do expensive data fetch many times.
# I've thought about caching the datafetch... but I'd rather only call
# get_data when I NEED to update the dataframe instead of using caching everywhere..
df = get_data()
df_filtered = df[df[filter_col].isin(filter_vals)] # <-- this filtering doesn't need new data fetch
return df_filtered.hvplot(...)
template.main.append(pn.Card(
render_data1,
...
render_data_n,
))
template.servable()
I’ve gone down several rabbit holes here, and I have several thoughts/questions:
- Whenever
get_data1
is called,render_data1
must also be called. Not sure how to link them properly in a way that allowsrender_data1
to run without fetching data again, butrender_data1
will always causeget_data1
to be run.- I did try to get something working with holoviz interactive based on the Interactive — hvPlot 0.8.0 documentation functions as input section, however then I had duplicated widets…!
- There are many pairs of
get_data_n
andrender_data_n
I’d like my code to be more dry- I thought I could create some sort of parametrized class that is controlled by the global widgets, but I ended up with an extremely verbose non-DRY pattern where I called
widget.link(class, value=parameter)
for all parameters in the class that I didn’t like at all. - Would custom components be helpful?
- I thought I could create some sort of parametrized class that is controlled by the global widgets, but I ended up with an extremely verbose non-DRY pattern where I called
- The whole file is layed out with only functions, should I try to make some massive class that is the dashboard? This is appealing to me because I will have many of these apps, but I got lost in the sauce when I started making a class-based app, so any examples would be helpful.
All the tutorials seem to be focused on pretty small scoped examples, so I’m really hoping for some link where someone has got something a bit beefier so I can see what “opinionated panel programming” looks like. There are just so many ways to tie things together and so many indecipherable dead ends that I’m feeling a bit lost. Any sense of direction that people could provide would be super helpful.
thank you all very much.