🏥 🏭 Working on the COVID-19 response in Canada? Plotly & the Canadian government can help you and your organization. Learn more and get in touch.

Plotly Dash served in Django - dash_bootstrap_components error

Hi,

I have set up a django site and embedded plotly dash into the urls. This has worked successfully. However, I am now trying to make the site ‘pretty’ and use

app = DjangoDash(‘app’, external_stylesheets=[dbc.themes.BOOTSTRAP])

I receive the below error.

Django version 3.0.4, using settings ‘UPS.settings’
Starting ASGI/Channels version 2.4.0 development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
HTTP GET /test/ 200 [0.13, 127.0.0.1:60098]
HTTP GET /django_plotly_dash/app/test/ 200 [0.03, 127.0.0.1:60098]
HTTP GET /django_plotly_dash/app/test/_dash-component-suites/dash_bootstrap_components/_components/dash_bootstrap_components.v0_9_0m1585057943.min.js 302 [0.01, 127.0.0.1:60098]
Not Found: /static/dash/component/dash_bootstrap_components/_components/dash_bootstrap_components.min.js
HTTP GET /static/dash/component/dash_bootstrap_components/_components/dash_bootstrap_components.min.js 404 [0.02, 127.0.0.1:60098]
HTTP GET /django_plotly_dash/app/test/_dash-layout 200 [0.05, 127.0.0.1:60098]
HTTP GET /django_plotly_dash/app/test/_dash-dependencies 200 [0.07, 127.0.0.1:60099]

  1. I have done pip install dash-bootstrap-components
  2. https://django-plotly-dash.readthedocs.io/en/latest/configuration.html#configuration-options - did all that.
  3. Please note - prior to trying to import dash_bootstrap_components as dbc and then trying to use dbc. whatever - I was able to use plotly dash successfully with 400 lines of code. Only introducing the bootstrap stuff is throwing errors and I have nooooooo idea what to do.

Thank you for your time

@avnj take a look at the django-plotly-dash documentation, particularly here which covers the configuration options. Fundamentally, some manipulation is needed to align the parts of a Dash app with routes in Django, particularly those of static assets.

There is also an example using dash-bootstrap-components in the demo part of the source repository.

Unfortunately the link you shared is the link I posted.

There seems to be an error using dash_bootstrap_components within Django

I also would like to add the below example copied and pasted works just fine in an IDE on my desktop.

However, that exact code imported into a djangodash app on Django will throw the errors. Django is ignoring the code that pip install dash-bootstrap-components installed.

import dash
import dash_bootstrap_components as dbc
import dash_html_components as html

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Navbar(
dbc.Container(
[
dbc.NavbarBrand(
[
html.Span(“A”, style={“color”: “red”}),
html.Span(“B”, style={“color”: “green”}),
html.Span(“C”, style={“color”: “blue”}),
]
),
dbc.Nav(
[
dbc.NavItem(dbc.NavLink(“Item 1”, href="#")),
dbc.NavItem(dbc.NavLink(“Item 2”, href="#")),
],
navbar=True,
),
]
)
)

if name == “main”:
app.run_server(debug=True)

Your problem is that you are trying to set external_stylesheets=[dbc.themes.BOOTSTRAP] - this won’t work. You need to set the add_bootstrap_links flag as per the code link. From the demo:

dd = DjangoDash("BootstrapApplication",
                serve_locally=True,
                add_bootstrap_links=True)

Edit: documentation isn’t clear on this point; have raised an issue in the github project

Hi,

I appreciate your comment. I made the code change. However, I still received 404 errors below.

then I only receive
HTTP GET /test/ 200 [0.08, 127.0.0.1:50127]
HTTP GET /static/channels/js/websocketbridge.js 404 [0.02, 127.0.0.1:50127]
HTTP GET /static/channels/js/websocketbridge.js 404 [0.03, 127.0.0.1:50127]
HTTP GET /django_plotly_dash/app/test/ 200 [0.04, 127.0.0.1:50128]
HTTP GET /django_plotly_dash/app/test/_dash-component-suites/dash_bootstrap_components/_components/dash_bootstrap_components.v0_9_0m1585057943.min.js 302 [0.01, 127.0.0.1:50128]
HTTP GET /static/dash/component/dash_bootstrap_components/_components/dash_bootstrap_components.min.js 404 [0.01, 127.0.0.1:50128]
HTTP GET /django_plotly_dash/app/test/_dash-layout 200 [0.07, 127.0.0.1:50128]
HTTP GET /django_plotly_dash/app/test/_dash-dependencies 200 [0.08, 127.0.0.1:50127]

Have you followed all of the configuration steps?

In particular, did you get any errors when running collectstatic, and can you validate that whitenoise is being used to serve static files?

Hi, I appreciate your time and your advice! I thought I did, but maybe not? My settings file is below`

Preformatted text`

"""
Django settings for UPS project.

Generated by 'django-admin startproject' using Django 3.0.4.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'XXXXXXXXXXXXXXXXX'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    # 'whitenoise.runserver_nostatic',#HEREEEEEEEEEEE
    'dpd_static_support', #hereeeeeeee
    'coe.apps.CoeConfig',
    'crispy_forms',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_plotly_dash.apps.DjangoPlotlyDashConfig',
    'channels',
    'channels_redis',
    'bootstrap4',

]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django_plotly_dash.middleware.BaseMiddleware', #hereeeeeeeeeeeeeee
    'whitenoise.middleware.WhiteNoiseMiddleware', #hereeee
    'django_plotly_dash.middleware.ExternalRedirectionMiddleware',#hereeee
]

ROOT_URLCONF = 'UPS.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'UPS.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'America/New_York'    #hereeeeeeeeeeeeee

USE_I18N = True

USE_L10N = True

USE_TZ = True

ASGI_APPLICATION = 'UPS.routing.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('127.0.0.1', 6379),],
        }
    }
}

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    'django_plotly_dash.finders.DashAssetFinder',
    'django_plotly_dash.finders.DashComponentFinder',
    'django_plotly_dash.finders.DashAppDirectoryFinder'
]

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATICFILES_LOCATION = 'static'
STATIC_URL = '/static/'
STATIC_ROOT = 'static'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
LOGIN_REDIRECT_URL = 'coe-home'
LOGIN_URL = 'login'
# STATICFILES_DIRS = [
#     os.path.join(BASE_DIR, 'static')]   # hereeeeeeeeeeee

X_FRAME_OPTIONS = 'SAMEORIGIN'      # hereeee

PLOTLY_DASH = {

    # Route used for the message pipe websocket connection
    "ws_route" :   "dpd/ws/channel",

    # Route used for direct http insertion of pipe messages
    "http_route" : "dpd/views",

    # Flag controlling existince of http poke endpoint
    "http_poke_enabled" : True,

    # Insert data for the demo when migrating
    "insert_demo_migrations" : False,

    # Timeout for caching of initial arguments in seconds
    "cache_timeout_initial_arguments": 60,

    # Name of view wrapping function
    "view_decorator": None,

    # Flag to control location of initial argument storage
    "cache_arguments": False,

    # Flag controlling local serving of assets
    "serve_locally": False,
}

PLOTLY_COMPONENTS = [

    'dash_core_components',
    'dash_html_components',
    'dash_renderer',
    'dpd_components',
    'dpd_static_support',
    'dash_bootstrap_components',
]


My html is

{% extends “coe/base.html” %}
{% load static %}

{% block content %}

{% load plotly_dash %}

<div class="{% plotly_class name='test' %} card" style="height: 100%; width: 110%">
    {% plotly_app_bootstrap name="test" aspect="16by9"%}
    {% plotly_message_pipe %}
</div>

{{ plot1 | safe }} # hereeeeeeeeeeeee

{% endblock content %}

And my python is
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_table
from django_plotly_dash import DjangoDash
import pandas as pd
import dash_bootstrap_components as dbc

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]
es = [‘https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css’]

app = DjangoDash(‘test’,
# serve_locally=True,
add_bootstrap_links=True)

app.layout = html.Div([
html.Div([dbc.Button(“Testing”)])

Once again, I have no problem writing regular plotly dash code with callbacks or using DBC outside Django. Once Django gets introduced my app just doesn’t load. This is a config problem.

Thank you so much for your time!!!

As the error you get is a 404 for the bootstrap js file/static/dash/component/dash_bootstrap_components/_components/dash_bootstrap_components.min.js can you check inside your STATIC_ROOT directory to see if it is present?

If it is, then you’ve got an issue with whatever is serving your static files. If you are running the Django debug server, then whitenoise is a good idea (and it can be useful for production depending on your reverse proxy configuration) - see the django-plotly-dash demo for an example of how it is used.

If it is not, then the issue is with the collection of static files. As well as the settings, the demo also has setup scripts that encapsulate the steps taken including collectstatic calls.