Django_plotly_dash with Apache and mod_wsgi is not working

Hello All,

Greetings of the new year.

I am trying to use Plotly Dash with Django app for creating a Dhasboard page. I used the django_plotly_dash package and made all the configuration as per the documentation. The page is working fine when I am running locally with python manage.py runserver but when I am deploying to UAT its failing. The UAT Django app is running on Windows Server + Apache httpd server + mod_wsgi +python 3.9 +Django 3.0. 10

I dont get any error in the apache server log , the application just stop responding to any http request. All the request queue up in pending state with django_ploty_dash config enabled. If I remove the configuration for django_plotly_dash the application starts responding again.

plotly file:

import dash

import dash_core_components as dcc

import dash_html_components as html

from dash.dependencies import Input,Output

import plotly.graph_objs as go

import pandas as pd

from django_plotly_dash import DjangoDash

import dash_bootstrap_components as dbc

df = pd.read_csv(‘C:/Data/gapminderDataFiveYear.csv’)

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

year_options =

for year in df[‘year’].unique():

year_options.append({'label':str(year),'value':year})

app.layout = html.Div([

            dcc.Graph(id='my-graph'),

            dcc.Dropdown(id='year-picker',options=year_options,value=df['year'].min())

])

@app.callback(Output(‘my-graph’,‘figure’),

        [Input('year-picker','value')])

def update_figure(selected_year):

#Filtered Dataframe based on selected year

filtered_df = df[df['year'] == selected_year]

traces =[]

for continent_name in filtered_df['continent'].unique():

    df_by_continent = filtered_df[filtered_df['continent'] == continent_name]

    traces.append(go.Scatter(

        x= df_by_continent['gdpPercap'],

        y = df_by_continent['lifeExp'],

        mode='markers',

        opacity=0.7,

        marker={'size':15},

        name=continent_name

    ))



return {'data':traces,

        'layout':go.Layout(title='Graph for Demo',

                            xaxis={'title':'GDP Per Capita','type':'log'},

                            yaxis={'title':'Life Expectancy'})

    }

django app settings.py:

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'welcome',

'announcement',

'document',

'report',

'django_plotly_dash.apps.DjangoPlotlyDashConfig',

]

X_FRAME_OPTIONS = ‘SAMEORIGIN’

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',

]

ROOT_URLCONF = ‘dse_application.urls’

TEMPLATES = [

{

    'BACKEND': 'django.template.backends.django.DjangoTemplates',

    'DIRS': [BASE_DIR/'templates'],

    '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',

            'welcome.context_processors.header_loader'

        ],

    },

},

]

WSGI_APPLICATION = ‘dse_application.wsgi.application’

Database

Settings | Django documentation | Django

DATABASES = {

 'default': {

    'ENGINE': 'django.db.backends.sqlite3',

     'NAME': str(os.path.join(BASE_DIR, "db.sqlite3")),

 }

}

#BASE_DIR / ‘db.sqlite3’,

Password validation

Settings | Django documentation | Django

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

Internationalization and localization | Django documentation | Django

LANGUAGE_CODE = ‘en-us’

TIME_ZONE = ‘UTC’

USE_I18N = True

USE_L10N = True

USE_TZ = True

Static files (CSS, JavaScript, Images)

Managing static files (e.g. images, JavaScript, CSS) | Django documentation | Django

STATIC_URL = ‘/static/’

#for PROD

STATIC_ROOT = ‘/static/’

MEDIA_URL = ‘/media/’

MEDIA_ROOT = PureWindowsPath(’//shareddrive/’).drive

Settings for Plotly Dashboard integration

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": True,

# Flag controlling local serving of assets

"serve_locally": True,

}

Staticfiles finders for locating dash app assets and related files

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',

]

Plotly components containing static content that should

be handled by the Django staticfiles infrastructure

PLOTLY_COMPONENTS = [

# Common components

'dash_core_components',

'dash_html_components',

'dash_renderer',

# django-plotly-dash components

'dpd_components',

# static support if serving local assets

'dpd_static_support',

# Other components, as needed

'dash_bootstrap_components',

]

Django urls.py:

from graph_interaction_demo import app

urlpatterns = [

path('admin/', admin.site.urls),

path('',views.home,name='home'),

path('contact/',views.contact,name='contact'),

path('aboutus/',views.aboutus,name='aboutus'),

path('login/', RedirectView.as_view(url='/admin'),name='login'), 

path('announcement/',include('announcement.urls')),

path('document/',include('document.urls')),

path('report/',include('report.urls')),

path('django_plotly_dash/', include('django_plotly_dash.urls')),

]

urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

Any suggestion what could be the issue or how to resolve this would be a great help.
Thank you in advance.

This sounds like some piece isn’t correctly configured for the apache server. Are you able to coax any error or other logging at all out of the process?

I’ve not had any cause to use Apache for serving Django for a long time, and definitely not on Windows, but this section on debugging techniques for the wsgi module might help you extract some useful information.

Thanks delsim for sharing the link. I will try the options.

hi @delsim , I tried the debugging process but there is nothing in the logs. Any http request to the server, just stays in pending state and nothing proceeds further. As soon as I remove django_plotly_dash configurations from settings.py, urls.py and restart the server everything start working smoothly again

This sounds like the python is not loading in your environment. Is it not possible to add some sort of logging (eg in wsgi.py or in the main urls.py file) that lets you know that the application is loading?

hi @delsim ,
I implemented logger in all the files and what I can debug is the problem is, the import statement of the plotly_dash file in the main urls.py

from . import graph_interaction_demo

the moment I comment this line the whole portal works fine except the page where the plotly_dash app is
integrated. The plotly_dash integrated page shows error ‘Unable to find stateless DjangoApp called simpleexample’
Any suggestion what could be the problem?

It sounds like something is going wrong when you import the graph_interaction_demo file, which I assume contains your application. The ‘Unable to find…’ error is simply the application reporting that you’ve not imported it.

First, I’d recommend making it an absolute, not a relative, import. If you can’t log any errors from importing it, then I would proceed by cutting down the file, eg by commenting out chunks of it, and from that determine which line is causing the problem.

Hi @delsim , thank you so much the guidance.

I was able to resolve the issue. I had to make two changes

  1. Add WSGIApplicationGroup %{GLOBAL} in httpd.conf and
  2. Move the application file to a folder and change the import statement to
    from dash_apps import graph_interaction_demo