Django Static Files

Django's staticfiles app gives every app a standard place to keep CSS, JavaScript, and images, plus a consistent way to build the URLs that serve them.

Configuring Static Files in settings.py

STATIC_URL defines the URL prefix used whenever a static file is referenced, such as /static/. STATICFILES_DIRS lists extra folders, outside of any single app, that Django should also search for static files during development. STATIC_ROOT is a separate, single folder used only in production, where collectstatic gathers every static file from every app so a real web server can serve them directly.

Example

# settings.py

# URL prefix used whenever a static file is referenced
STATIC_URL = '/static/'

# Extra folders Django also searches during development
STATICFILES_DIRS = [
    BASE_DIR / 'static',
]

# Folder collectstatic copies every static file into for production
STATIC_ROOT = BASE_DIR / 'staticfiles'

Using Static Files in Templates and Production

Inside a template, {% load static %} must appear before any {% static %} tag is used. The {% static %} tag then builds the correct URL for a file using STATIC_URL, so templates never hardcode the path directly. When it is time to deploy, running the collectstatic management command copies every static file from every installed app into STATIC_ROOT so a production web server, or a tool like WhiteNoise, can serve them.

Example

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="{% static 'css/site.css' %}">
</head>
<body>
    <img src="{% static 'images/logo.png' %}" alt="Logo">
</body>
</html>
  • Each installed app can keep its own static/<app_name>/ folder, and Django finds it automatically
  • {% load static %} must be loaded once per template before any {% static %} tag is used
  • STATIC_ROOT and STATICFILES_DIRS should never point to the same folder
  • The development server only serves static files automatically while DEBUG = True

Example

# terminal, run once before deploying
python manage.py collectstatic --noinput

# Output ends with something like:
# 127 static files copied to '/path/to/project/staticfiles'.
Setting / CommandPurpose
STATIC_URLURL prefix used by {% static %} tags and generated links
STATICFILES_DIRSExtra folders Django searches for static files in development
STATIC_ROOTSingle folder collectstatic copies every static file into
collectstaticManagement command that gathers all static files for deployment
Note: Always reference files with {% static 'css/site.css' %} instead of hardcoding /static/css/site.css. If STATIC_URL ever changes, or the files move to a CDN, every template keeps working without edits.
Note: Setting DEBUG = False turns off Django's automatic static file serving. In production you need to run collectstatic and either configure your web server to serve STATIC_ROOT or add a package like WhiteNoise.

Exercise: Django Static Files

Which setting defines the URL prefix used to serve static files?