Callback not fired from dcc.Location url change

Hi,

I have a multipage dash app.
That i would like to load some data from the backend everytime when subpage is visited.

I create a dash app with dcc.Location and callbacks:

def init_app(config):
    """Initialize Dash App"""
    app = DashProxy(
        server=SERVER,
        index_string=INDEX_STRING,
        external_stylesheets=EXTERNAL_STYLESHEETS,
        external_scripts=EXTERNAL_SCRIPTS,
        use_pages=True,
        update_title=None,
    )
   (...)

    app.layout = dbc.Container(
        [
            dcc.Location(id="url", refresh=False),
            (...)
            dcc.Store(id="refresh_history_time", data=-1),
            dash.page_container,
        ],
        fluid=True,
    )

    _register_pages(...)
    _create_callbacks(app, backend_url)

    return app

Create callback using “url”, “pathname”

def create_callbacks(app, hostname):
    """Create callbacks"""

    @app.callback(
        Output("line_mapping", "data"),
        Input("url", "pathname"),
        prevent_initial_call=True,
    )
    def update_page(url):
        logging.debug("Trigger line mapping")
        if url != "/":
            raise PreventUpdate
       (...)

    @app.callback(
        Output("refresh_history_time", "data"),
        Input("url", "pathname"),
        prevent_initial_call=True,
    )
    def trigger_history_refresh(url):
        if url != "/history":
            raise PreventUpdate

        logging.info("Trigger history")
        return time.time()

and another callbacks for subpage tableupdate:

    @app.callback(
        Output("results_table", "rowData"),
        Output("history_pagination", "active_page"),
        Output("history_last_params", "data"),
        Output("history_pagination", "max_value"),
        Input("refresh_history_button", "n_clicks"),
        Input("serial_search_button", "n_clicks"),
        Input("refresh_history_time", "data"),
        Input("history_pagination", "active_page"),
        State(..)
        prevent_initial_call=True,
    )
    def refresh_history(  # pylint: disable=too-many-arguments,too-many-positional-arguments, too-many-locals, too-many-branches
        _,
        search_n_clicks,  # pylint: disable=unused-argument
        refresh_history_time,  # pylint: disable=unused-argument
        active_page,
        (...)
    ):
        """Refresh history page"""

        caller_id = get_caller_id(dash.callback_context)
        logging.debug("History triggered by %s", caller_id)
        params = {}

It works on localhost.
But in production, when dashboard is accessed from another machine, Is see url pathanme are both fired, but
refresh_history is not.

I’ve tried removing trigger_history_refresh callback completely and trigger refresh_history directly from Input(“url”, “pathname”) but even on localhost it does not work.

I’d appreciate any ideas what could be wrong?

Thanks!

Could you make a complete minimal example that can be run and replicates the error? It’s hard to see what’s wrong based on the code snippets you posted.

1 Like

@AnnMarieW thank you for you comment.

We debugged the issue a little bit deeper since, as I wrote, the code works locally,

The problems seems to be with production deployments:

  • Windows server
  • https/ reverse proxy

When we access :8050 the callback trigger_history fires,
But when we configured Windows IIS to redirect port 80 to 8050, refresh_history callback does not fire anymore.

This pseudocode (chaining callbacks via dcc.State refresh_history_time):

    @app.callback(
        Output("refresh_history_time", "data"),
        Input("url", "pathname"),
        prevent_initial_call=True,
    )
    def trigger_history_refresh(url):
        if url != "/history":
            raise PreventUpdate

        logging.info("Trigger history")
        return time.time()

    @app.callback(
        Output("results_table", "rowData"),
        Input("refresh_history_button", "n_clicks"),
        Input("refresh_history_time", "data"),
        prevent_initial_call=True,
    )
    def refresh_history( _, refresh_history_time):
        """Refresh history page"""
        logging.debug("History triggered")

does not work.

However, surprisingly, when I simulate click on a existing button refresh_history_button (which is another way to trigger refresh):

    @app.callback(
        Output("refresh_history_button", "n_clicks"),
        Input("url", "pathname"),
        State("refresh_history_button", "n_clicks"),
        prevent_initial_call=False,
    )
    def trigger_history_refresh(url, n_clicks):
        if url != "/history":
            raise PreventUpdate

        logging.info("Trigger history")
        return n_clicks + 1

    @app.callback(
        Output("results_table", "rowData"),
        Input("refresh_history_button", "n_clicks"),
        prevent_initial_call=True,
    )
    def refresh_history(_):
        """Refresh history page"""
        logging.debug("History triggered")

It works.

Do you have any ideas why?
Are there any known problems with dcc.Location callbacks or chaining callback when using https, Windows Server or reverse proxy ?

What if you change the location I’d to be _pages_location and drop the url?