How can I pass service class references in multi page app

Hello,

I am not sure if my design makes any sense at this point, but I will go ahead and ask here before re-designing.

Essentially, I have a multipage app where I would like to have a single instance of a Data Access object (more or less), insofar as, it has multiple connections to databases, and if I can not have to make this class more than once (Singleton essentially), that would be ideal.

Please excuse any pythonic style issues, as I’m bouncing around languages and “styles” I realized that DataService should be more like data_service (etc).

app.py:

from dataservice import DataService

app = Dash(
    __name__,
    use_pages=True,
    title='Data Plots',
    external_stylesheets=[dbc.themes.BOOTSTRAP],
)
dataService = None
def get_dataservice():
    if dataService is None:
        dataService = DataService()
        return dataService
    else:
        return dataServce

So, essentially, I have done an unnecessary getter as I am sort of in between implementations. Theoretically, I would only need to call app.dataService to get it (assuming I have a reference to my app.py)

In one of my Page(s).py I have some code as this:

left_select = dbc.Select(id="expid-dropdown", options=[{"label":x,"value":x} for x in **dash.get_app().get_dataservice()**.EXPIDS])

Eventually, I put that left_select in side the layout object (this is just an example, it’s not that actual implementation)

layout = html.Div(left_select)

As I read about the lifecycle of the dash app, it looks like I can’t quite get things in the right order or perhaps, I need to wrap everything in functions?

Either way, I receive the error when I try to start the app:

dbc.Select(id="expid-dropdown", options=[{"label":x,"value":x} for x in dash.get_app().get_dataservice().EXPIDS])
                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Dash' object has no attribute 'get_dataservice'

I didn’t see a lot of get_app() documentation, and I assumed it was a reference to the app.py.

I’m not sure exactly what you are trying to do with get_dataservice but it’s not part of the app object, so the dash.get_app() won’t work. Perhaps put the data service into a separate module and imported it where needed?

1 Like

Thanks for the reply!

I think I’m applying a design pattern improperly in the Dash framework. I also did not fully understand whether dash.get_app() returns the instantiated “app.py” that I made (which uses the dash.app() instantiation).

I made a separate python class/module in dataservice.py that, when instantiated, provides common data and database access functions. I was trying to avoid instantiating this module throughout the dash pages of my multipage app. So I thought I would be clever, and put it in the app.py, and provide a function in my app.py file to provide a reference to the once-instantiated dataservice.py module.

MVC-esque. I had seen some users do a sort of class wrapper for the app.py as opposed to the documentation, and it felt a little hacky; it doesn’t mean it’s bad, but I just wanted to make sure there weren’t any hooks I couldn’t identify that might have been available. All good! I’ll just be very cognizant of the connection pool, etc.

In any case, I am a huge fan of dash and plotly, and am pushing for its use at my organization, and hope to continue to expand on it for our vast quantities of data :slight_smile:

1 Like