Getting Server Error (500) when setting debug to false due to manifest not including css files
I have an app that I've built using Django and React + Vite. Everything runs fine with Debug set to True, but once I set it to false I get a Server Error with the console output of:
ValueError: Missing staticfiles manifest entry for 'reactjs/inspector-B1mMLMX5.css'
The file reactjs/inspector-B1mMLMX5.css
exists and is getting generated properly when running npm run build
and the generated manifest file has an entry for it in the css property of the file that imports it:
"Inspector/InspectorApp.jsx": {
"file": "reactjs/inspector-FdX6WZL2.js",
"name": "inspector",
"src": "Inspector/InspectorApp.jsx",
"isEntry": true,
"imports": [
"_Loading-CnrJ4Xi6.js"
],
"css": [
"reactjs/inspector-B1mMLMX5.css"
]
},
It appears that with my current settings, running python manage.py collectstatic --noinput
generates a separate manifest file called staticfiles.json
, however this does not seem to be the issue as with some previous settings (i.e. not using WhiteNoise), I was getting the same error but referencing the correct Vite manifest file.
Here is my current settings.py:
"""
Django settings for ChiroComp project.
Generated by 'django-admin startproject' using Django 5.1.1.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""
from pathlib import Path
import os, sys, dj_database_url
from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Support env variables from .env file if defined
env_path = load_dotenv(os.path.join(BASE_DIR, '.env'))
load_dotenv(env_path)
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY','django-insecure-+3-2#pi_$ac^i_*63hysa)33y34*xw6g--&^lxu%$o4u3$g_fg')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv('DJANGO_DEBUG', '') == 'True'
DEVELOPMENT_MODE = os.getenv('DJANGO_DEVELOPMENT_MODE', 'False') == 'True'
ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1,localhost').split(',')
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djecrety',
'django_vite',
'rest_framework',
'drf_spectacular',
'ImageCompare',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'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',
]
ROOT_URLCONF = 'ChiroComp.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',
],
},
},
]
WSGI_APPLICATION = 'ChiroComp.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
if DEVELOPMENT_MODE is True:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
elif len(sys.argv) > 0 and sys.argv[1] != 'collectstatic':
if os.getenv('DJANGO_DATABASE_URL', None) is None:
raise Exception('DJANGO_DATABASE_URL environment variable is not defined')
DATABASES = {
'default': dj_database_url.parse(os.environ.get('DJANGO_DATABASE_URL'))
}
# Login path
LOGIN_URL = '/login/'
# Password validation
# https://docs.djangoproject.com/en/5.1/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',
},
]
# Security
SECURE_HSTS_SECONDS = 300
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# Logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
'propogate': False,
},
},
}
# Internationalization
# https://docs.djangoproject.com/en/5.1/topics/i18n/
LANGUAGE_CODE = 'en-au'
TIME_ZONE = 'Australia/Adelaide'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = 'static/'
STORAGES = {
'staticfiles': {
'BACKEND': 'whitenoise.storage.CompressedManifestStaticFilesStorage',
},
}
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Media Storage
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# Django Vite config
DJANGO_VITE = {
'default': {
'dev_mode': DEBUG,
}
}
# Django Rest Framework config
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
'COMPONENT_SPLIT_REQUEST': True,
}
vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { join, resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig(() => {
const INPUT_DIR = './frontend';
const OUT_DIR = './static';
return {
plugins: [react()],
base: '/static/',
root: resolve(INPUT_DIR),
build: {
manifest: 'manifest.json',
emptyOutDir: true,
outDir: resolve(OUT_DIR),
assetsDir: 'reactjs',
rollupOptions:{
input: {
inspector: join(INPUT_DIR, 'Inspector/InspectorApp.jsx'),
compare: join(INPUT_DIR, 'Compare/CompareApp.jsx'),
},
},
},
};
});
I have checked all the other Django files and haven't found any errors in them (they all work and display correctly in debug mode). At this stage, I've tried every solution that I've been able to find and none of them have solved the issue.