Skip to content

Chapter 11: Static and Media Files

11.1 Static File Management

STATIC_URL Configuration

Static files include CSS, JavaScript, images and other files that don't change frequently. Django provides a complete static file management mechanism.

Basic configuration:

python
# settings.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# Static file URL prefix
STATIC_URL = '/static/'

# Static file directories in development environment
STATICFILES_DIRS = [
    BASE_DIR / "static",
    BASE_DIR / "assets",
]

# Static file collection directory in production environment
STATIC_ROOT = BASE_DIR / "staticfiles"

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

App-level static file organization:

myapp/
    static/
        myapp/
            css/
                style.css
                responsive.css
            js/
                main.js
                utils.js
            images/
                logo.png
                favicon.ico

Using static files in templates:

html
{% load static %}

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
    <!-- CSS files -->
    <link rel="stylesheet" type="text/css" href="{% static 'myapp/css/style.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'myapp/css/responsive.css' %}">
</head>
<body>
    <!-- Image -->
    <img src="{% static 'myapp/images/logo.png' %}" alt="Logo">
    
    <!-- JavaScript files -->
    <script src="{% static 'myapp/js/main.js' %}"></script>
</body>
</html>

collectstatic Command

In production environments, use the collectstatic command to collect all static files to the STATIC_ROOT directory:

bash
# Collect all static files
python manage.py collectstatic

# Force collection (overwrite existing files)
python manage.py collectstatic --noinput --clear

# Collect static files for specific apps only
python manage.py collectstatic --noinput --verbosity=2

# Show files to be collected without actually executing
python manage.py collectstatic --dry-run

Customize collectstatic behavior:

python
# management/commands/custom_collectstatic.py
from django.contrib.staticfiles.management.commands.collectstatic import Command as CollectStaticCommand
from django.contrib.staticfiles.storage import staticfiles_storage
import os

class Command(CollectStaticCommand):
    def collect(self):
        # Execute custom logic before collection
        self.stdout.write("Starting to collect static files...")
        
        # Call parent method
        collected = super().collect()
        
        # Execute custom logic after collection
        self.stdout.write("Static file collection completed!")
        
        return collected

CSS/JS File Organization

Recommended static file organization structure:

static/
    css/
        base.css
        components/
            buttons.css
            forms.css
            navigation.css
        pages/
            home.css
            blog.css
        vendor/
            bootstrap.min.css
            fontawesome.css
    js/
        base.js
        components/
            modal.js
            dropdown.js
        pages/
            blog.js
        vendor/
            jquery.min.js
            bootstrap.bundle.min.js
    images/
        logos/
            main-logo.png
            favicon.ico
        icons/
            search.svg
            menu.svg
    fonts/
        custom-font.woff2
    scss/
        base.scss
        components/
            _buttons.scss
        main.scss

Handling SCSS files in Django:

python
# settings.py
# Install django-sass-processor
# pip install django-sass-processor

INSTALLED_APPS = [
    # ...
    'sass_processor',
]

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

SASS_PROCESSOR_ENABLED = True
SASS_PROCESSOR_ROOT = BASE_DIR / 'static'
scss
// static/scss/main.scss
$primary-color: #007bff;
$secondary-color: #6c757d;

@import "components/buttons";
@import "components/forms";

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

.header {
    background-color: $primary-color;
    color: white;
    padding: 1rem;
}

Development vs Production Environment

Static file configuration in different environments:

python
# settings/base.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent.parent

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / "static",
]

# settings/development.py
from .base import *

DEBUG = True

# Provide static files directly from source directories in development
STATICFILES_DIRS = [
    BASE_DIR / "static",
    BASE_DIR / "assets",
]

# settings/production.py
from .base import *

DEBUG = False

# Provide static files from collection directory in production
STATIC_ROOT = BASE_DIR / "staticfiles"

# Enable static file compression
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

# Configuration when using CDN
# STATIC_URL = 'https://cdn.example.com/static/'

Optimizing static files in production environment:

python
# settings/production.py
# Static file cache control
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

# Compress static files
# Install django-compressor
# pip install django-compressor

INSTALLED_APPS = [
    # ...
    'compressor',
]

MIDDLEWARE = [
    # ...
    'compressor.middleware.CompressorMiddleware',
]

COMPRESS_ENABLED = True
COMPRESS_OFFLINE = True  # Offline compression
COMPRESS_CSS_FILTERS = [
    'compressor.filters.css_default.CssAbsoluteFilter',
    'compressor.filters.cssmin.rCSSMinFilter',
]
COMPRESS_JS_FILTERS = [
    'compressor.filters.jsmin.JSMinFilter',
]

Static file compression in templates:

html
{% load static %}
{% load compress %}

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
    
    {% compress css %}
    <link rel="stylesheet" type="text/css" href="{% static 'css/base.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static 'css/components/buttons.css' %}">
    <link rel="stylesheet" type="text/x-scss" href="{% static 'scss/main.scss' %}">
    {% endcompress %}
</head>
<body>
    <!-- Page content -->
    
    {% compress js %}
    <script src="{% static 'js/vendor/jquery.min.js' %}"></script>
    <script src="{% static 'js/base.js' %}"></script>
    <script src="{% static 'js/components/modal.js' %}"></script>
    {% endcompress %}
</body>
</html>

With these configurations, you can effectively manage static files in Django projects, ensuring static resources are correctly provided in both development and production environments.

Summary

Django static file management provides a complete solution:

  1. ✅ STATIC_URL configuration defines static file access paths
  2. ✅ collectstatic command collects all static resources
  3. ✅ Reasonable file organization structure improves maintainability
  4. ✅ Differentiated configuration for development and production environments
  5. ✅ Static file compression optimizes performance

Proper static file management is an important part of web application performance optimization.

Next Article

We will learn about media file handling.

11.2 Media File Handling →

Directory

Return to Course Directory

Released under the [BY-NC-ND License](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.en).