matheus dimon
matheus dimon

Reputation: 21

Static files not loaded when deploy a django web page in vercel(with whitenoise)

when the project is deployed shows this error here is my settings.py:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
DEBUG = True
ALLOWED_HOSTS = ['*']

INSTALLED_APPS = [
    'me',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    "whitenoise.runserver_nostatic",
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

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 = 'Matheus.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 = 'Matheus.wsgi.application'

...

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / "staticfiles" / "static"

if DEBUG:
    STATICFILES_DIRS=['staticfiles']
    STATIC_ROOT = None
else:
    STATICFILES_DIRS=[]
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

# Whitenoise Storage Class  - Apply compression but don’t want the caching behaviour
STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'

here is my vercel.json:

{
  "version": 2,
  "builds": [
      {
          "src": "Matheus/wsgi.py",
          "use": "@vercel/python",
          "config": {
              "maxLambdaSize": "15mb",
              "runtime": "python3.12"
          }
      },
      {
          "src": "build.sh",
          "use":"@vercel/static-build",
          "config":{
              "distDir": "staticfiles"
          }
      }
  ],
  "routes": [
      {
          "src":"/static/(.*)",
          "dest":"/static/$1"
      },
      {
          "src": "/(.*)",
          "dest": "Matheus/wsgi.py"
      }
  ]
}

here is my build.sh:

#!/bin/bash

# Update pip
echo "Updating pip..."
python3.12 pip install -U pip

# Install dependencies

echo "Installing project dependencies..."
python3.12 -m pip install -r requirements.txt

# Make migrations
echo "Making migrations..."
python3.12 manage.py makemigrations --noinput
python3.12 manage.py migrate --noinput
#Install whitenoise
echo Installing white noise..."
python3.12 manage.py whitenoise
# Collect staticfiles
echo "Collect static..."
python3.12 manage.py collectstatic --noinput --clear

echo "Build process completed!"```

wsgi config :

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Matheus.settings')

application = get_wsgi_application()

# vercel config

app = application # add this line.


https://github.com/Matheus-Dimon/me/tree/teste

I want to a config to change that can make the deploy serves the staticfiles.

Upvotes: 1

Views: 675

Answers (4)

leele2
leele2

Reputation: 1

Just spent ages trying to get this working, main thing is that when serving static elements in production (DEBUG = False) django will not let you serve them without running --insecure flag. Hence, why we need white noise.

Note this solution works with using function (instead of build) which allows you to increase max_timeout options.

This is how I got it running on vercel, main thing was outputting the static files (after collectstatic) to the correct directory inside the vercel.json and changing STATIC_URL accordingly if DEBUG was True or False (Handled using .env file)

Full working example: https://github.com/leele2/timesheet-xlsx-to-ics

Settings.py

from pathlib import Path
from os import getenv
from dotenv import load_dotenv

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# Load environment variables from .env
load_dotenv(BASE_DIR / '.env')
DEBUG = getenv('DEBUG', 'False') == 'True'

INSTALLED_APPS = [
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    "whitenoise.middleware.WhiteNoiseMiddleware",
]

# Static files (CSS, JavaScript, images)
if DEBUG:
    STATIC_URL = '/dev_static/'  # Development URL for static files
else:
    STATIC_URL = '/static/'  # Production URL for static files

# Add your local static file directories here
STATICFILES_DIRS = [
    BASE_DIR / "dev_static",  # This allows Django to look for static files in the 'dev_static' directory
]

# Directory where static files will be stored after running collectstatic
STATIC_ROOT = BASE_DIR / 'static'

# Optional: Use manifest storage for cache busting (adding hash to filenames)
STATICFILES_STORAGE = "whitenoise.storage.CompressedStaticFilesStorage"

urls.py

from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('', include('some_views.urls'))
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

vercel.json

{
  "outputDirectory": "static/",
  "buildCommand": "python3 manage.py collectstatic --noinput",
  "functions": {
    "api/wsgi.py": {
      "maxDuration": 15
    }
  },
  "routes": [
    {
      "src": "/(.*)",
      "dest": "api/wsgi.py"
    }
  ]
}

Upvotes: 0

Croolic
Croolic

Reputation: 161

Firstly check on vercel if you realy have folder staticfiles/static or static. I had not any despite of having python manage.py collectstatic in buildfiles.sh and distDir similary to yours in vercel.json. Static files of course have not worked (with DEBUG = False). So, firstly, I decided to change vercel.json in line 7 and make ditDir: 'static' like below:

{
  "builds": [
    {
      "src": "build_files.sh",
      "use": "@vercel/static-build",
      "config": {
        "distDir": "static"
      }
    },
    {
      "src": "/czarny_kot/wsgi.py",
      "use": "@vercel/python",
      "config": { "maxLambdaSize": "15mb" }
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "czarny_kot/wsgi.py"
    }

  ]
}

Secondly, i've deleted line with collectstatic from buildfiles.sh. After I set lines in settings.py like bellow:

STATICFILES_DIRS = [
    # ...
]

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'

MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'

my urls.py:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', HomeViews.as_view(), name='home'),
    path('tinymce/',include('tinymce.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

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

Finally I run python manage.py collectstatic locally and after committed and pushed all stuff to github. As u can see on this page: czornykot.pl statics works - there is no lack of any static image, css, or js. Hope it's going to work on your page :)

edit: BASE_DIR / ... works if u have this in settings.py:

from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent

I'm using Whitnoise.

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

Upvotes: 0

matheus dimon
matheus dimon

Reputation: 21

i found the solution with these configs: in vercel.json i change this :

"src": "build_files.sh",
  "use": "@vercel/static",
  "config": {
    "distDir": "staticfiles_build"

in settings.py this config:

STATIC_URL = 'static/'
STATICFILES_DIRS = os.path.join('me' , 'static'),
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

and url.py of app put this :

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

Upvotes: 0

Juan Molina
Juan Molina

Reputation: 1

I did it this way when Debug is False...

In urls.py (the main one)

from django.conf import settings
from django.views.static import serve
from django.contrib import admin
from django.urls import path, include, re_path


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('main.urls')),
    re_path(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),

    re_path(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}),

For the settings.py... I did this:


STATIC_URL = '/static/'

MEDIA_URL = '/media/'



if DEBUG:

  STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

else:

  STATIC_ROOT = os.path.join(BASE_DIR, 'static')



MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

If Debug is True, do it this way... urls.py:

from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('main.urls'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


settings.py

import os
...
...
...
STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static/']
MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')


Upvotes: 0

Related Questions