Mr. Editor-in-chief Mr. Editor-in-chief June 9, 2024 Updated April 24, 2026

4 Ways of Serving Static Files in Django

1. Django development server (Not recommended for production)

@settings.py

STATIC_ROOT = BASE_DIR / 'static'
  • python manage.py collectstatic
  • python manage.py runserver --nostatic Go to localhost:8000/admin and you will see static files won't be loaded.

2. Whitenoise

  • python manage.py shell
  • from django.conf import settings
  • settings.STATICFILES_STORAGE # Default value: django.contrib.staticfiles.storage.StaticFilesStorage
  • pip install whitenoise

@settings.py

......
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'whitenoise.runserver_nostatic', # Add code line 1
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', # Add code line 2
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

......
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'static'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage' # Add code line 3
......
  • python manage.py runserver --nostatic Go to localhost:8000/admin and you will see static files is served by whitenoise even if we turned off Django development static files server by adding --nostatic in the end.

Another way to test production environment is to serve the Django with gunicorn

  • pip install gunicorn
  • deactivate
  • source venv/bin/activate
  • gunicorn core.wsgi:application --bind 0.0.0.0:8000 After restart the server, you will see that Django project is no longer served by the development server

3. Nginx

  • sudo cp -r ~/core/static /var/www/static

@/etc/nginx/sites-available/default

server {

    ######################
    location /static/ {
        root /var/www;
    }
    ######################
}

4. AWS Simple Storage Service(S3)

  • Create a AWS S3 bucket
    • Bucket name: django-static-2024
    • Turning off block all public access
  • Amazon S3 > Buckets > django-static-2024 > Edit bucket policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::django-static-2024/*"
        }
    ]
}
  • Amazon S3 > Buckets > django-static-2024 > Edit cross-origin resource sharing (CORS)
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "POST",
            "GET",
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]
  • Amazon S3 > Buckets > django-static-2024 > Edit static website hosting >
    • Enable
    • Redirect requests for an object: django-static-2024.s3.ap-northeast-1.amazonaws.com
  • pip install django-storages boto3

@settings.py

## Comment out whitenoise and other static file settings
......
    # 'whitenoise.runserver_nostatic',
......
    # 'whitenoise.middleware.WhiteNoiseMiddleware',
......
# STATIC_URL = 'static/'
# STATIC_ROOT = BASE_DIR / 'static'
# STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'


AWS_ACCESS_KEY_ID = os.environ.get(AWS_ACCESS_KEY_ID)
AWS_SECRET_ACCESS_KEY = os.environ.get(AWS_SECRET_ACCESS_KEY)
AWS_STORAGE_BUCKET_NAME = os.environ.get(AWS_STORAGE_BUCKET_NAME)
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.ap-northeast-1.amazonaws.com'
AWS_S3_STATIC_DIR = 'static'
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_S3_STATIC_DIR}/'
STATICFILES_STORAGE= 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_DIRS = [BASE_DIR / 'static', ]
AWS_S3_FILE_OVERWRITE = False
  • python manage.py collectstatic
  • It looks that both the development server and the gunicorn server work now.