Collectstatic - Running Django in Production

Posted on Dec 29, 2020

The Problem

After successfully developing a Django application locally with DEBUG = True you get it hosted and none of the styling is appearing. One of the things Django does when DEBUG = True is serves static files, like CSS, JavaScript and images. When DEBUG = False Django stops serving these files and they have to be exposed separately from the application.

collectstatic

The collectstatic command collects all of the django default static files for the admin site , as well as all of the static files in the STATICFILES_DIRS specified in mysite/settings.py and places them into the folder specified in STATIC_ROOT in mysite/settings.py.

Django Static File Settings

There are three settings in mysite/settings.py that are important for serving static files: STATIC_URL, STATIC_ROOT and STATICFILES_DIRS.

STATIC_URL

Tells your application the path to your static files. For example if you have a static file, /css/mystyling.css and your STATIC_URL = “/static/“ Django will use the path /static/css/mystyling.css to access this file.

STATIC_ROOT

Tells Django what folder to collect all of the styling into. For example if your STATIC_ROOT = “staticfiles“ when you run python manage.py collectstatic Django will create a new folder called static_files and it will put all of your static files into that folder in their folder structure.

STATICFILES_DIRS

Tells Django where to look for the custom static files you have added to your application. For example if you have all of your static files in a folder called static then you will want STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]. This way it will look into the correct folder to find your static files.

Putting it All Together

These settings are all well and good, but they need to be combined correctly to get everything to work. These are the settings I would recommend:

# settings.py
STATIC_URL = “/static/“
STATIC_ROOT = “staticfiles”
STATICFILES_DIRS = [
	os.path.join(BASE_DIR, "static"),
]

All of your static files should be located in the static/ folder in your Django project.

What this will do is expose all of the static files correctly in test mode because they will all be served by Django from the static/ folder.

When you run collectstatic all of the files in the static/ folder will be collected into the staticfiles folder along with the Django admin static files, so they can be served by your hosting provider separately from the application.

Hosting Configuration - Serving the Static Files

You will notice that collectstatic will collect all of your static files into a new staticfiles folder, but your application is still set up to use the /static/ path to access the files.

Currently there will be nothing at /static/, so you need to set up your hosting provider to serve the folder, static_files, your STATIC_ROOT in mysite/settings.py, at /static/.

In AWS Elastic Beanstalk it looks like this:

# .ebextensions/django.config

option_settings:
  aws:elasticbeanstalk:container:python:
    WSGIPath: mysite.wsgi:application
  aws:elasticbeanstalk:environment:proxy:staticfiles:
        /static: staticfiles

This is telling AWS to expose the contents of the folder staticfiles at the URL /static/, so all of the static files are available to the Django application and can be used.