6. Static files

Robert Crowther Feb 2022
Last Modified: Feb 2023

PrevNext

Django has a system called ‘static’ files. You will probably use it on any site that delivers static material, such as images and CSS/JS files. Which means most conventional websites. If it’s images you want, go to the separate image discussion,

The ‘static’ system answers a problem that most website systems have. When building a site in a modular way, you need to provide static files with the modules. But when serving the static files, it is better to gather these files in one place. It may be better to deliver the files from a different server than the Django instance. I’ve written a seperate article about the Django ‘static’ system. Do note that the writeup in Django documentation is laboured and complex.

This is a muddle. Me, I’d bash through it all without thinking too much.

Settings

In siteName/settings.py, check these exist. They are included in a project skeleton, ,

INSTALLED_APPS = [
    ...
    'django.contrib.staticfiles',
]

# and...
STATIC_URL = 'static/'

That will achieve nothing, but they need to be there.

We need to add some extra information on how to find static files. Add these two, or check they exist,

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

FileSystemFinder searches in configured filepaths. AppDirectoriesFinder searches in apps for static files.

Ok, static files are gathered in a universal folder. This is done by a management command,

/manage.py collectstatic

Create the folder (can be any name),

mkdir files_static

Ok, lets tell the code commands where to gather static files. In /settings.py, add this setting,

STATIC_ROOT = BASE_DIR / 'files_static'

As usual with Django, it will not do much if you do not ask. Current configuration looks for static files in apps. For most standard websites it would be sensible to have a project‐wide/site directory for statics—site‐wide CSS etc. Assuming you have one of these, you can ask FileSystemFinder to look in that directory also. For specialist sites, not necessary, otherwise add this to settings, probably next to the other static configuration,

STATICFILES_DIRS= [
    PROJECT_DIR / "static",
]

(told you in Step 2 the project setting PROJECT_DIR can be useful).

Now ‘collectstatic’ will gather files from the app directories, the central, project‐wide ‘static’ directory, then dump them into STATIC_ROOT. Try it—collectstatic copies files, so there can be no damage. Watch all those useful files like CSS, JS, favicons, and stock images dump into STATIC_ROOT,

/manage.py collectstatic

If you’ve not seen this before, you may be surprised by how many there are—the admin app alone delivers over 100 files.

Also, a development server can serve static files, either directly from the apps, or from the STATIC_ROOT directory. These files will appear on the configured URL ‘/static/..’.

Git

If you are using Git, you probably don’t want to commit gathered static files. So add the STATIC_ROOT to the .gitignore,

files_static/**

URLs

Guess what? You are not obviously serving any of the files. You only set up the app code to gather files. This will work on a development server, because the ‘staticfiles’ middleware has a builtin view that will will serve the files in DEBUG mode. Assuming you have the standard port and admin app on board, you can try now,

http://127.0.0.1:8000/static/admin/css/base.css

All should be good.

Static app in templates

In any template add,

{% load static %}

and then use the static tag,

{% static '/css/style.css' %}

All this does is prefix the URL with STATIC_URL.

Refs

Official instructions. Confused,

https://docs.djangoproject.com/en/3.2/howto/static-files/

Django static reference,

https://docs.djangoproject.com/en/3.2/ref/contrib/staticfiles/

Media

‘Media’ in Django is a kind of static file handling. See the guide for image and other uploads.

Serve uploaded media using staticfiles

Only works in debug mode, and for local filestorage.

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)