How To: Serve Django Static Files and Templates

CSS, JavaScript, and typefaces are all essential components of any modern online application. Django offers a lot of flexibility in terms of how these files are used, but this might be confusing for newbies. The Django web server will provide static files for local development, and only little configuration is necessary. The external package WhiteNoise, as well as various additional processes, are necessary for production.

We’ll look at how to set up static files for local development and later production in this lesson.

Django Serve Static Files In Local Development

Multiple apps are frequently found in a single Django project. Django looks for a static directory containing static files within each app by default. So, if one of your apps is called blog, and you want to add a CSS file called base.css to it, you’ll need to create a new directory called blog/static, then add the file to it, making the address blog/static/style.css.

Because most Django projects have many apps and shared static files, it’s normal to create a top-level folder called static instead. The mkdir command can be used to add this from the command line:

$ mkdir staticCode language: JavaScript (javascript)

There is a single line of setup for static files named STATIC URL near the bottom of the settings.py file, which is the location of static files in our project.

# settings.py
STATIC_URL = '/static/'Code language: PHP (php)

Static files will be kept at http://127.0.0.1:8000/static/ or http://localhost:8000/static/, respectively. We must add a configuration for STATICFILES DIRS telling Django to also look within a static folder in order to notify Django of our new top-level static folder.

# settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = (str(BASE_DIR.joinpath('static')),) # newCode language: PHP (php)

This example makes use of pathlib, which is loaded by default in Django 3.1+. You’d use STATICFILES DIRS = [os.path.join(BASE DIR,’static’)] if you’re using a settings.py file from 3.0 or earlier.

Create subfolders for each sort of static file, such as css, js, and image, within the new static folder. These can be added using the mkdir command on the command line:

$ mkdir static/css
$ mkdir static/js
$ mkdir static/imgCode language: JavaScript (javascript)

All of your static assets can now be added. As a result, the base.css file would be at static/css/base.css. The styling will not be available if you run the local webserver now (python manage.py runserver). This is due to the fact that static assets must be loaded into the templates directly.

Loading Static Files Into Templates

In a template, loading static files is a two-step process:

  • add {% load static %} at the top of the template
  • add the {% static %} template tag with the proper link

Let’s pretend your Blog project has a base.html file. The procedure for performing both updates would be as follows:

<!-- templates/base.html -->
{% load static %}
<!DOCTYPE html>
<html>
<head>
  <title>Learn Django</title>
  <link rel="stylesheet" href="{% static 'css/base.css' %}">
</head>
...
</html>Code language: HTML, XML (xml)

The changes will be visible if you save and reload the web page. The following is how to add links to images in an img folder or JavaScript in a js folder:

<img src="{% static 'img/path_to_img' %}">
<script src="{% static 'js/base.js' %}"></script>Code language: HTML, XML (xml)

Collect Static Files Using collectstatic

Static files will be served by the local Django server, but not by a production server like Gunicorn or uWSGI. As a result, Django includes the collectstatic command, which compiles all static files into a single directory appropriate for production deployment. The STATIC ROOT option specifies the absolute path to these gathered files, which are commonly referred to as staticfiles. The last component is STATICFILES STORAGE, which is the file storage engine utilized when using the collectstatic command to collect static files. It is set to django.contrib.staticfiles.storage.StaticFilesStorage by default.

As a result, four static file configurations are necessary, and the python manage.py collectstatic command must be executed each time there is a change to recompile all static components into a single directory.

# settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = (str(BASE_DIR.joinpath('static')),) # new
STATIC_ROOT = str(BASE_DIR.joinpath('staticfiles')) # new
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' # newCode language: PHP (php)

Then run the command python manage.py collectstatic

(env) $ python manage.py collectstatic

A new staticfiles directory with folders for admin (the built-in admin has its own static files), staticfiles.json, and whatever directories are in your static folder will be created.

If you add a new static file to static, it will be accessible locally. Unless you execute python manage.py collectstatic every time, it’s only for production where the file won’t be present. As a result, collecting static data is commonly included in deployment processes and is done by default on Heroku.

Overview

  • STATIC_URL is the URL location of static files located in STATIC_ROOT
  • STATICFILES_DIRS tells Django where to look for static files in a Django project, such as a top-level static folder
  • STATIC_ROOT is the folder location of static files when collectstatic is run
  • STATICFILES_STORAGE is the file storage engine used when collecting static files with the collectstatic command.

Django Serve Static Files In Production

Even though we’ve properly configured our Django project to gather static files, there’s one more step that isn’t covered in the official Django documentation. This is the WhiteNoise setup for serving static files in production. The first step is to install the most recent package version:

(env) $ pipenv install whitenoise==5.1.0

Then make three changes to the settings.py file:

  • add whitenoise to the INSTALLED_APPS above the built-in staticfiles app
  • under MIDDLEWARE, add a new WhiteNoiseMiddleware on the third line
  • change STATICFILES_STORAGE to use WhiteNoise.
# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'whitenoise.runserver_nostatic', # new
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', # new
    '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/'
STATICFILES_DIRS = (str(BASE_DIR.joinpath('static')),)
STATIC_ROOT = str(BASE_DIR.joinpath('staticfiles')) 
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # newCode language: PHP (php)

That concludes the tutorial. So that the files are stored using WhiteNoise, run python manage.py collectstatic once again. Then, with confidence, deploy to your preferred hosting platform.

Conclusion

In this article, you’ve learnt how to work with and serve static files in Django Web Development framework for both local development and production. As always, If you have found this article useful do not forget to share it and leave a comment if you have any questions. Happy Coding 🙂

Comments

Leave a Reply