Instantiation on Running Script

Hey everyone! So I’m building out the beginnings of what is going to be a relatively large application, and I have found that all of the layout components in my multipage app are being defined and called upon starting my script. Each page dynamically calls functions to populate the contents of dropdowns, etc. based on the database, but every function gets called when I first start the application and I would assume that that will grow at an unsustainable rate as I continue to add pages to my application. I was wondering if there is any way to not call the functions that populate each of my dropdowns upon first running the script, only calling them when a client browser attempts to open that page on their machine, if that makes sense. I’d be happy to try to explain the problem again if that doesn’t quite make sense. Thank you in advance! :slight_smile:

Hi,

Your question makes a lot of sense, and I will try to answer it to the best of my knowledge.

It is not possible to do it by importing the page submodule after the app starts. The app needs all callbacks defined when the process start, so even if you could (maybe?) import the layout from a different file on the fly, none of the callbacks n the page will work. Plus, this is a very bad idea.

Now, your concern about startup when fetching data from a DB is very much dependent on how you intend to deploy the application. If your deployment environment automatically kills the process running the app when idle for some time (for example, Heroku with free dynos), then this can be a problem because it is very likely that the service will start the process when a user request the page. If the process rarely stops, then this is less of an issue.

The other side of this question is if the values that you are fetching from the DB could be updated after your application starts. If you fetch just when the app starts, it is of course not possible to update the dropdown options after that. The same is true for other values calculated at runtime: as an example, if you set a date picker value to be dt.datetime.today() and deploy the app, the selected value will still be the day the process started.

One simple alternative for the case of multi-page application is to update the dropdown values of each page when you load it on the layout using a callback. Since Dash will trigger all callbacks depending on a given input when the component is added to the layout, you can simply use the id or children of a static element, like:

# page1.py

layout = html.Div(
    id="page1",
    children=[
        dcc.Dropdown(id="dd1"),
        dcc.Dropdown(id="dd2"),
    ]
)

@callback(
    Output("dd1", "options"),
    Output("dd2", "options"),
    Input("page1", "id")
)
def update_options(dummy):
     # Here you fetch from the DB
     return #....

More performant alternatives are:

You can use dcc.Store to save the dropdown options on the clientside, so if the user loads one of the pages, goes to another page and back, there is no need to fetch again from the DB. You can find multiple examples discussed in the community.

You can also consider server side caching, so the cache can be shared across multiple users. It might be harder to deploy the app in certain environments.

Hope this helps! :slight_smile:

1 Like