CodeMIRAI
0 XP

Static files

2 min read 1 runnable example Quiz included

Static files are the files your site sends exactly as they are: CSS, JavaScript, images, fonts. Django needs to know where they live and what URL to serve them from.

Where static files go

Like templates, static files live in each app, in a folder namespaced with the app's name:

Output
courses/
    static/
        courses/
            css/course.css
            img/badge.png

Files shared by the whole site go in a top-level folder, which you list in the settings:

Python
STATIC_URL = "static/"                     # the URL prefix for static files
STATICFILES_DIRS = [BASE_DIR / "static"]   # extra folders to search, besides each app's static/
STATIC_ROOT = BASE_DIR / "staticfiles"     # where collectstatic copies everything, for deployment

django.contrib.staticfiles must be in INSTALLED_APPS, as it is in every new project.

Linking to static files

Python
import django
from django.conf import settings

settings.configure(
    STATIC_URL="/static/",
    TEMPLATES=[{"BACKEND": "django.template.backends.django.DjangoTemplates"}],
)
django.setup()

from django.template import Context, Template

t = Template("""{% load static %}<link rel="stylesheet" href="{% static 'courses/css/course.css' %}">
<img src="{% static 'courses/img/badge.png' %}" alt="Badge">""")
print(t.render(Context()))

{% load static %}, at the top of the template, makes the tag available, and {% static 'path' %} turns a path into a full URL. Never hard-code /static/... in templates: when the files move to a CDN or get versioned names at deployment, the tag updates every link for you.

In development

With DEBUG = True, the runserver command serves static files automatically. Create the file, refresh the page, done.

In production: collectstatic

A production web server shouldn't ask Django for every image. Before deploying, gather every app's static files into one folder:

Terminal
python manage.py collectstatic
Output
1240 static files copied to '/srv/codemirai/staticfiles'.

The web server (Nginx, or a CDN) then serves STATIC_ROOT directly. A popular simpler option is the WhiteNoise package, which lets Django serve its own static files efficiently, with caching headers and compression, and needs only a line of middleware.

Media files: uploads

Files uploaded by users, like profile pictures, are called media and are kept separate from your own static files:

Python
MEDIA_URL = "media/"
MEDIA_ROOT = BASE_DIR / "media"
Python
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    avatar = models.ImageField(upload_to="avatars/", blank=True)

In a template, {{ profile.avatar.url }} gives the file's URL. Keep the two apart: static files are part of your code and change when you deploy; media files are data that changes whenever users upload something.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.