Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dash Uploader callbacks fail in a Multi-page app with Dash Extensions #119

Open
yordanovn opened this issue Apr 21, 2023 · 1 comment
Open

Comments

@yordanovn
Copy link

Hi,
I'm building a multi-page Dash application. It utilises functionality from the dash-extensions package, however I experience issues when I want to use a dash-uploader callback function.

The error I get is: AttributeError: 'DashProxy' object has no attribute 'blueprint'.

I managed to figure out that it occurs, because the DashProxy's callback method is using the blueprint attribute, however the du.callback is trying to call it before the attribute is assigned to the instance. I don't know how to work around this issue.

Note: I'm not sure if dash-uploader is supposed to work with dash-extensions and this is an issue or rather a feature request.

Here's how the code is structured:

app.py:

from dash_extensions.enrich import DashProxy, ServersideOutputTransform
app = DashProxy(__name__, use_pages=True, transforms=[ServersideOutputTransform()])

file_upload.py:

import dash
from dash import html, Output
import dash_uploader as du

app = dash.get_app()
du.configure_upload(app=app, folder='./uploads')
dash.register_page(__name__, path='/')
layout = html.Div(children=[
    du_file_upload := du.Upload(id='du-file-upload'),
    du_uploads := html.Div(id='du-uploads')
] )

@du.callback(
    output=Output("du-uploads", "children"),
    id="du-file-upload",
)
def get_a_list(filenames):
    return html.Ul([html.Li(filenames)])

Here is the full Traceback:

Traceback (most recent call last):
  File "/Users/user/PycharmProjects/machine-learning/ROICalculator/ticket_analysis/app.py", line 16, in <module>
    app = DashProxy(__name__, use_pages=True, transforms=[ServersideOutputTransform()])
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash_extensions/enrich.py", line 352, in __init__
    super().__init__(*args, **kwargs)
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash/dash.py", line 494, in __init__
    self.init_app()
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash/dash.py", line 578, in init_app
    self.enable_pages()
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash/dash.py", line 2044, in enable_pages
    self._import_layouts_from_pages()
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash/dash.py", line 2016, in _import_layouts_from_pages
    spec.loader.exec_module(page_module)
  File "<frozen importlib._bootstrap_external>", line 843, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Users/user/PycharmProjects/machine-learning/ROICalculator/ticket_analysis/pages/file_upload.py", line 101, in <module>
    def get_a_list(filenames):
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash_uploader/callbacks.py", line 105, in add_callback
    dash_callback = settings.app.callback(
  File "/Users/user/virtualenv/ticket-analysis/lib/python3.8/site-packages/dash_extensions/enrich.py", line 358, in callback
    return self.blueprint.callback(*args, **kwargs)
AttributeError: 'DashProxy' object has no attribute 'blueprint'
@yordanovn
Copy link
Author

I managed to resolve my issue by unwrapping the du.callback method within my own page definition.

The change is that instead of calling app.callback which would have used DashProxy.callback we now call callback which is imported from dash. By doing this we are bypassing the issue that the blueprint attribute doesn't yet exist for the DashProxy instance.

I will keep the issue as Open, since there still might be a fix or a documentation update within the dash-uploader project to better accommodate integration with dash-extensions.

Here is an example:

app.py:

from dash_extensions.enrich import DashProxy, ServersideOutputTransform
app = DashProxy(__name__, use_pages=True, transforms=[ServersideOutputTransform()])

file_upload.py:

import dash
from dash import html, Output
import dash_uploader as du
from dash_uploader.callbacks import create_dash_callback
import dash_uploader.settings as settings

app = dash.get_app()
du.configure_upload(app=app, folder='./uploads')
dash.register_page(__name__, path='/')
layout = html.Div(children=[
    du_file_upload := du.Upload(id='du-file-upload'),
    du_uploads := html.Div(id='du-uploads')
] )

def update_du_uploads(filenames):
    return html.Ul([html.Li(filenames)])

dash_callback = create_dash_callback(
    update_du_uploads,
    settings,
)

callback(
    Output('du-uploads', 'children'),
    Input('du-file-upload', 'isCompleted'),
    State('du-file-upload', 'fileNames'),
    State('du-file-upload', 'upload_id')
)(dash_callback)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant