Search code examples
djangodjango-staticfilesdjango-static

Django stops serving static files when DEBUG is False


I use Docker Compose along with this Dockerfile that copies the static folder into /static:

FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install --upgrade pip && pip install -r requirements.txt
COPY static /static/
COPY . /code/

And in my settings files I use:

if env == "dev":
    DEBUG = True
else:
    DEBUG = False
    SECURE_CONTENT_TYPE_NOSNIFF = True
    SECURE_BROWSER_XSS_FILTER = True
    X_FRAME_OPTIONS = "DENY"

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

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

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

The static files are working in dev but when I change the env to prod, I start getting 404 errors.

So you see the problem ?


Solution

  • While it is **strongly discouraged* to serve static files from Django in production (and for VERY good reasons), I often need to anyway.

    In some cases its perfectly acceptable (low traffic, REST API only server, etc). If you need to do that, this snippet should help out. Adjust the re_path or use url() if thats your django flavor.

    from django.contrib.staticfiles.views import serve as serve_static
    
    def _static_butler(request, path, **kwargs):
        """
        Serve static files using the django static files configuration
        WITHOUT collectstatic. This is slower, but very useful for API 
        only servers where the static files are really just for /admin
    
        Passing insecure=True allows serve_static to process, and ignores
        the DEBUG=False setting
        """
        return serve_static(request, path, insecure=True, **kwargs)
    
    urlpatterns = [
        ...,
        re_path(r'static/(.+)', _static_butler)
    ]