Django CDN integration

Introduction

A Django CDN integration can deliver CSS, JavaScript, images, and other static files from edge servers closer to application visitors. Django continues to render the application on the origin while the CDN handles the files collected for production.

This guide shows how to configure Django's native staticfiles app with ManifestStaticFilesStorage, run collectstatic, and expose the collected directory through an Nginx origin for CDNsun Static Pull. The procedure was tested with Django 5.2.17.

Before you start

  • This tutorial shows how to integrate a CDN service into a website. In this particular demo example we will use:
    • barsoom-cdn.cdnsun.org as the CDN Service Domain, and
    • https://barsoom.cdnsun.org as the website URL (i.e. barsoom.cdnsun.org is the Origin Domain).
  • Please visit the Services/How-To section to obtain your CDN Service Domain.
  • Before you take any steps please back up your files and database.
  • To integrate a CDN service on https:// website the CDN service must have SSL enabled.
  • If your website embeds custom fonts then please first enable CORS for them.
  • Before you take any steps please make sure that your CDN Service Domain is ready-to-use here.

Create CDN Static service

Please refer to Creating a CDN Static service for more details.

How to enable CDN in Django

  1. Open the project's settings.py file. Set STATIC_URL to the complete HTTPS URL of your CDN Service Domain and set STATIC_ROOT to the directory that will contain collected production assets:
    STATIC_URL = "https://barsoom-cdn.cdnsun.org/static/"
    STATIC_ROOT = BASE_DIR / "staticfiles"

    Keep the trailing slash in STATIC_URL. Do not use STATIC_ROOT as a source directory; Django writes the production output there when you run collectstatic.

  2. In the same file, configure the staticfiles storage alias to use ManifestStaticFilesStorage:
    STORAGES = {
        "default": {
            "BACKEND": "django.core.files.storage.FileSystemStorage",
        },
        "staticfiles": {
            "BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
        },
    }

    Defining STORAGES replaces Django's default dictionary, so retain the default alias as shown unless the application already uses another file storage backend. The manifest backend adds a content hash to collected filenames and updates supported references inside CSS files.

  3. Load Django's static template library and reference assets with the static template tag:
    {% load static %}
    <link rel="stylesheet" href="{% static 'showcase/styles.css' %}">
    <script src="{% static 'showcase/app.js' %}" defer></script>
    <img src="{% static 'showcase/network.svg' %}" alt="Global delivery network">

    Store application assets under an app-specific path such as showcase/static/showcase/. The template tag combines the configured CDN Service Domain with the manifest's versioned filename. Avoid hard-coding root-relative /static/ URLs in templates.

  4. From the project root, collect the production static files:
    python manage.py collectstatic --noinput

    Django copies files from installed applications and project static directories into STATIC_ROOT. With the manifest backend enabled, the output includes versioned paths such as showcase/styles.c0c6b9a6e1c7.css and the corresponding staticfiles.json manifest.

  5. Make the collected /static/ path publicly available on the application origin. For Nginx, add a location whose alias points to the exact STATIC_ROOT directory:
    location ^~ /static/ {
        alias /var/www/example/staticfiles/;
        expires 1y;
        access_log off;
    }

    Replace /var/www/example/staticfiles/ with the application's collected directory. Keep the public /static/ path unchanged so the CDNsun Static service can retrieve each requested file from the origin in Pull mode.

  6. Continue serving dynamic Django requests through the application's production WSGI or ASGI server. For example, Gunicorn can bind to a local port behind Nginx:
    gunicorn --workers 2 --bind 127.0.0.1:8001 myproject.wsgi:application

    Replace myproject with the Python package containing wsgi.py. Nginx should serve /static/ directly and proxy the remaining requests to the application server.

  7. Run collectstatic during every production deployment that changes static assets. Changed content receives a new versioned filename, so it can use a fresh CDN URL while previously cached files remain available to older application pages.
  8. Open the public site and confirm that the frontend remains styled normally and static assets load from the CDN Service Domain.
    Styled Django application loading versioned CSS, JavaScript, and an image through the CDN Service Domain

Verify & Troubleshoot

  • View HTML source code of your web pages to verify that you are using CDN, you should see source attribute of your images, CSS, JavaScript, etc. beginning with your CDN Service Domain.
    Frontend HTML proof that static assets are loaded from the CDN Service Domain
  • Don't see your CDN Service Domain in the source code of your web pages? If your website is using any cache plug-in/mechanism then you might want to clear/flush its cache.
  • Having trouble with custom fonts? Please refer to Using custom fonts with CDN - setting CORS for more details.
  • Still having trouble? Check your CDN URLs using our content check tool or please refer to Debugging a CDN service for more hints.

Contact Us

 __   __   _    _    _    _   
 \ \\/ // | || | || | || | || 
  \   //  | || | || | || | || 
  / . \\  | \\_/ || | \\_/ || 
 /_//\_\\  \____//   \____//  
 `-`  --`   `---`     `---`