AnnMarieW / dash-bootstrap-templates

A collection of 52 Plotly figure templates with a Bootstrap theme. Two theme switch components. Stylesheet to apply Bootstrap themes to Plotly Dash components.
https://hellodash.pythonanywhere.com/
MIT License
135 stars 25 forks source link

AIO external_url pointing to a local folder troubles #42

Open spiqueras opened 1 month ago

spiqueras commented 1 month ago

Hi, thanks for the library.

I've been looking at using dash-bootstrap-templates with django-plotly-dash. Just looking at using one of the themes so the page looks nicer, not giving the user a theme changer.

Importing dash-bootstrap-templates is adding the AIO componentes whether they're used or not, which register their js with the following code: https://github.com/AnnMarieW/dash-bootstrap-templates/blob/dfa2b3207d9a8729cfc6ebace4ee566139ebaf83/src/aio/__init__.py#L13

When I instruct django-plotly-dash to embed the js imports needed for the app (with serve_locally set to False), the following line is added to the html:

[...]
<script src="/Users/spiqueras/[SOME_MORE_LOCAL_FOLDERS]\clientsideCallbacks.js"></script>
[...]

The url then gets interpreted as a relative url (e.g. localhost:port/Users/...) which obviously fails with a 404 Not Found.

Now I have absolutely no idea how it's working for anyone else (I assume some build step is involved or django-plotly-dash is being dumb) and I realize that my setup with django-plotly-dash is unconventional, but I'm looking at my options to either avoid the AIO components entirely if possible.

spiqueras commented 1 month ago

Separately, I'd like to ask why does this library use a separate package (aio) for ThemeSwitchAIO/ThemeChangerAIO instead of having them under dash_bootstrap_templates? Just curious, it'd have saved me some time trying to figure out where aio came from 😄

AnnMarieW commented 1 month ago

Hi @spiqueras

Thanks for reporting. Can you try version 1.1.2 and see if you get the same results?

spiqueras commented 1 month ago

Hi @spiqueras

Thanks for reporting. Can you try version 1.1.2 and see if you get the same results?

Hi. Tested 1.1.2, no errors there.

For what is worth my temp fix in 1.2.4 is to monkeypatch the library before creating the dash app:

def break_dash_bootstrap_templates_aio():
    # Empties _js_dist in dash-bootstrap-templates' aio package to prevent adding the wrong script
    import aio
    aio._js_dist = []
sdidier-dev commented 1 month ago

Hi @spiqueras ! Can you try with this simple example with dash_bootstrap_templates v1.2.4 that doesn't use any AIO ThemeSwitchAIO/ThemeChangerAIO ?

from dash import Dash, dcc, html
import plotly.express as px
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template

load_figure_template("vapor")

app = Dash(__name__, external_stylesheets=[dbc.themes.VAPOR])

df = px.data.gapminder()

dff = df[df.year.between(1952, 1982)]
dff = dff[dff.continent.isin(df.continent.unique()[1:])]
fig = px.line(
    dff, x="year", y="gdpPercap", color="continent", line_group="country"
)

app.layout = html.Div([
    html.H1("Dash Bootstrap Template Demo", className="bg-primary text-white p-2"),
    html.Div(
        [
            dbc.Button("Primary", color="primary"),
            dbc.Button("Secondary", color="secondary"),
            dbc.Button("Success", color="success"),
            dbc.Button("Warning", color="warning"),
            dbc.Button("Danger", color="danger"),
            dbc.Button("Info", color="info"),
            dbc.Button("Light", color="light"),
            dbc.Button("Dark", color="dark"),
            dbc.Button("Link", color="link"),
        ],
    ),
    dcc.Graph(figure=fig)
])

if __name__ == "__main__":
    app.run(debug=True)

That works fine here, I guess that django-plotly-dash is messing around...

{5A6E65CD-3FA8-47C9-81A9-BEE4DC5D01C6}

spiqueras commented 1 month ago

Can you try with this simple example with dash_bootstrap_templates v1.2.4 that doesn't use any AIO ThemeSwitchAIO/ThemeChangerAIO ?

from dash import Dash, dcc, html
import plotly.express as px
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template

load_figure_template("vapor")

app = Dash(__name__, external_stylesheets=[dbc.themes.VAPOR])

df = px.data.gapminder()

dff = df[df.year.between(1952, 1982)]
dff = dff[dff.continent.isin(df.continent.unique()[1:])]
fig = px.line(
    dff, x="year", y="gdpPercap", color="continent", line_group="country"
)

app.layout = html.Div([
    html.H1("Dash Bootstrap Template Demo", className="bg-primary text-white p-2"),
    html.Div(
        [
            dbc.Button("Primary", color="primary"),
            dbc.Button("Secondary", color="secondary"),
            dbc.Button("Success", color="success"),
            dbc.Button("Warning", color="warning"),
            dbc.Button("Danger", color="danger"),
            dbc.Button("Info", color="info"),
            dbc.Button("Light", color="light"),
            dbc.Button("Dark", color="dark"),
            dbc.Button("Link", color="link"),
        ],
    ),
    dcc.Graph(figure=fig)
])

if __name__ == "__main__":
    app.run(debug=True)

Hi @sdidier-dev

When running that example serve_locally is set to True, so clientsideCallbacks.js is served normally. But I am running Dash with serve_locally set to False. If I modify these lines:

app = Dash(__name__, external_stylesheets=[dbc.themes.VAPOR], serve_locally=False)
app.enable_dev_tools(dev_tools_serve_dev_bundles=False)
Full example code ```python from dash import Dash, dcc, html import plotly.express as px import dash_bootstrap_components as dbc from dash_bootstrap_templates import load_figure_template load_figure_template("vapor") app = Dash(__name__, external_stylesheets=[dbc.themes.VAPOR], serve_locally=False) app.enable_dev_tools(dev_tools_serve_dev_bundles=False) df = px.data.gapminder() dff = df[df.year.between(1952, 1982)] dff = dff[dff.continent.isin(df.continent.unique()[1:])] fig = px.line( dff, x="year", y="gdpPercap", color="continent", line_group="country" ) app.layout = html.Div([ html.H1("Dash Bootstrap Template Demo", className="bg-primary text-white p-2"), html.Div( [ dbc.Button("Primary", color="primary"), dbc.Button("Secondary", color="secondary"), dbc.Button("Success", color="success"), dbc.Button("Warning", color="warning"), dbc.Button("Danger", color="danger"), dbc.Button("Info", color="info"), dbc.Button("Light", color="light"), dbc.Button("Dark", color="dark"), dbc.Button("Link", color="link"), ], ), dcc.Graph(figure=fig) ]) if __name__ == "__main__": app.run(debug=True) ```

With that change, opening http://127.0.0.1:8050 will fire a request like this one:

GET http://127.0.0.1:8050/ ... /.venv/lib/python3.11/site-packages/aio/clientsideCallbacks.js

Which matches what I was seeing with django-plotly-dash, i.e. a local folder path being interpreted as a relative url.