Python Django Static Files

Last Updated: 30 Sep, 2026

What Are Static Files in Django? How to Add, Load and Collect Them

Static files in Django are the CSS, JavaScript, images and fonts that are the same for every visitor. Django manages them with the built-in django.contrib.staticfiles app. You store them in static/ folders, reference them in templates with {% static %}, and run collectstatic to gather them into one folder for production.

Static files are different from media files. Media files are uploaded by users at runtime, such as profile photos or documents. Mixing the two up is the most common reason images and stylesheets fail to load.

Static Files vs Media Files in Django

Static files Media files
Who creates them Developers, as part of the code Users, by uploading at runtime
Examples style.css, app.js, logo.png, fonts Profile photos, resumes, product images
Settings STATIC_URL, STATICFILES_DIRS, STATIC_ROOT MEDIA_URL, MEDIA_ROOT
In templates {% static ‘css/style.css’ %} {{ user.photo.url }}
In Git? Yes (source folders) No

 

How to Manage Static Files in Django: The Settings That Matter

Setting Purpose Example
STATIC_URL URL prefix for static files in the browser “static/”
STATICFILES_DIRS Extra source folders outside apps (for shared, project-wide assets) [BASE_DIR / “static”]
STATIC_ROOT Single folder where collectstatic copies everything for production BASE_DIR / “staticfiles”
STORAGES[“staticfiles”] Storage backend, e.g. for hashed filenames or cloud storage ManifestStaticFilesStorage or WhiteNoise

 

Django also looks inside every installed app’s static/ folder automatically. Namespace app files the same way as templates, as blog/static/blog/css/style.css, so two apps’ style.css files don’t collide.

Version note: since Django 4.2, the storage backend is configured with the STORAGES setting. The older STATICFILES_STORAGE setting was removed in Django 5.1, so older tutorials that use it will break on current versions.

Load the static tag library once at the top of each template that uses it, then link each file with {% static %}. Never hard-code /static/… paths; the tag builds the correct URL and picks up hashed filenames in production.

{% load static %}

<link rel=”stylesheet” href=”{% static ‘blog/css/style.css’ %}”>

<script src=”{% static ‘blog/js/app.js’ %}” defer></script>

<img src=”{% static ‘blog/img/logo.png’ %}” alt=”Blog logo”>

 

How to Collect Static Files in Django for Production

With DEBUG = True, runserver serves static files straight from the app folders and STATICFILES_DIRS. With DEBUG = False, Django stops serving them, so before deploying you:

  1. Set STATIC_ROOT, for example BASE_DIR / “staticfiles”.
  2. Run python manage.py collectstatic. It copies every static file from apps and STATICFILES_DIRSinto STATIC_ROOT.
  3. Serve STATIC_ROOTwith your web server (Nginx location /static/), a CDN or cloud storage, or with the WhiteNoise package directly from your Django/Gunicorn process.

# settings.py (production with WhiteNoise)

STATIC_URL = “static/”

STATIC_ROOT = BASE_DIR / “staticfiles”

MIDDLEWARE.insert(1, “whitenoise.middleware.WhiteNoiseMiddleware”)

STORAGES = {

“default”: {“BACKEND”: “django.core.files.storage.FileSystemStorage”},

“staticfiles”: {“BACKEND”: “whitenoise.storage.CompressedManifestStaticFilesStorage”},

}

 

How to Add Static Files (CSS, JavaScript and Images) to a Django Project

You will create app-level and project-level static folders, link CSS, JavaScript and an image in a template, and prepare everything for production with collectstatic. It takes 7 steps and about 15 minutes.

Prerequisites

  • A Django project with a blogapp and a template rendered by a view.
  • contrib.staticfilesin INSTALLED_APPS (included by default).
  • DEBUG = Truewhile developing.

Steps

Step 1: Create a namespaced app static folder

Inside the app, create static/blog/ with css, js and img subfolders.

blog/

└── static/

└── blog/

├── css/style.css

├── js/app.js

└── img/logo.png

 

Step 2: Add some CSS and JavaScript

Put a visible rule in style.css and a console message in app.js so you can confirm both load.

/* style.css */

body { background: #F5F8FF; }

 

// app.js

console.log(“Static JS loaded”);

 

Step 3: Add a project-level static folder (optional)

For assets shared across apps, create static/ at the project root and register it.

# settings.py

STATIC_URL = “static/”

STATICFILES_DIRS = [BASE_DIR / “static”]

 

At the top of the template, load the tag library, then link each file.

{% load static %}

<link rel=”stylesheet” href=”{% static ‘blog/css/style.css’ %}”>

<script src=”{% static ‘blog/js/app.js’ %}” defer></script>

<img src=”{% static ‘blog/img/logo.png’ %}” alt=”Logo” height=”40″>

 

Step 5: Check in the browser

Run python manage.py runserver, reload the page and open devtools. The Network tab should show 200 responses for all three files, and the console should print the message.

python_static_files

Step 6: Set STATIC_ROOT for deployment

Add an output folder that is separate from your source folders, and add it to .gitignore.

STATIC_ROOT = BASE_DIR / “staticfiles”

 

Step 7: Run collectstatic

Copy all static files into STATIC_ROOT, ready to be served by Nginx, a CDN or WhiteNoise.

python manage.py collectstatic –noinput

django_static_run_collecstatic