Django Collectstatic: Serve Django Static Files for Local & Production Development

This post is going to cover how to configure static files for local and production development for your Django project. We are going to look at what static files are, what the collectstatic command is and how it works, and finally how to serve the static files and load them in your templates.

What are Static Files in Django

The look, feel, and functionality of websites frequently change depending on who visits them. It’s not uncommon for one user to receive completely different content from another on the same website. However, even as this content evolves, there will always be a few parts of the site that remain unchanged for everyone. We refer to these parts as “static”.

a favicon is an example of a static image

Static files are any content that can be sent to a user without being modified in response to their interactions with the website. Because the server sends the exact same file to every user, static content is incredibly easy to distribute over the web. Static files in a Django project are commonly made up of CSS stylesheets, JS scripts, images, and so on.

The Difference Between Static Files and Media Files

The difference between Static files and Media files is typically confusing to most Django newbies. This is because both static files and media files can be files of the same type like images for example. Some images can be found as static and others as media files.

The difference between Static files and Media files is that Static files are from the code of the project, while media files are files uploaded by the users or the admins of the project to the database. In other words, Media files are rendered from the database, static files from the app’s server itself.

How to Configure & Serve your Django Static Files for Local Development.

The best way to configure static files for your Django project is to create a static folder at the root of your Django project, then in your settings.py register it as a static file directory.

1. Create a static folder at the root of Django project and register it in settings.py

The first step is to add a folder called static at the root of your Django project.

...
β”œβ”€β”€ static #here
|   β”œβ”€β”€ css
|   |    └── style.css
β”‚   β”œβ”€β”€ js
|   └── imgs 
└── manage.py

Once you create this folder, it’s usually a good idea to create other sub-folders that contain static files of the same type. For example a css folder for all the CSS stylesheets of your Django project, an imgs folder for all the static images of your Django project, and a js folder for JS scripts. Depending on the number of static files, other sub-folders worth creating are icons, fonts, vendor etc. Especially if you’re using bootstrap offline.


Another approach you can take is to create a static folder for each app in your Django project. This approach is the one favored by Django but it is going to be a lot of work if you are going to do it for each and every app in your Django project, especially if you have a lot of them.

...
β”œβ”€β”€ blog #django app
|  ...
|   └── static
|          └── blog
└── manage.py

However, what is good about this approach is that once you do this, there are no other configurations you have to do. Django will automatically figure out that it is the static folder for the app. What’s only left at that point is to load the static files in the templates.

2. Add the static folder to STATICFILES_DIRS in settings.py

In the settings.py file of your Django project, locate the STATIC_URL variable and write the following code below it:

By default, the STATIC_URL is already set and it is set to '/static/'. This means that each static file URL for this Django project will start withΒ /media/Β then followed by anything that we set it to be. For example, an image called logo.png can be accessed by going toΒ http://127.0.0.1:8000/static/logo.png. Using the static is another way of writing that same URL as you shall see in the next section. You can change this setting to something else, but it’s best to leave it as is.

STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR/'static']

The above STATICFILES_DIRS is pointing to the static folder we just created in the base folder of our Django project. As you can see, it is a list. This means that if you have any other folders in your Django project that are acting as static file directories, you have to include them in this list for them to be recognized by Django.

For example, if there is a static folder in BASE_DIR/'static' and another one in 'app/static', you have to include both of them in STATICFILES_DIRS list as follows:

STATICFILES_DIRS = [
         BASE_DIR/'static', 
         'blog/static'
]

How To Load Static to Templates

The main goal of doing all this is to display our static files to the user at the end. So assuming that you have configured your template files, let’s write some HTML code, then style it using the CSS, just as a case study. This case study assumes you have enough Django knowledge to add a suitable view and URL pattern for the page to render.

In your templates folder, create an HTML file called base.html and add the following code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    ➊<link rel="stylesheet" href="styles.css">
    <title>Document</title>
</head>
<body>
    <h1>Hello World</h1>
</body>
</html>

In the static folder, create a file called styles.css and add the following code.

h1 {
    color: red;
}

Now when you run the local server, you will see that there isn’t a style that has been applied although we have linked the files in the HTML at ➊.

Here are the steps to follow in order to load the styles in the templates properly:

1. Add {% load static %} at the top of template file

For every template that will need some static files, you have to add the {% load static %} tag at the top of the file. Without this, you won’t be able to apply the static links to your templates.

{% load static %} #new

<!DOCTYPE html>
<html lang="en">
<head>
...

The static template looks like this: {% static 'link' %}. Where link is the link to the suitable static file. So we should edit our CSS link at ➊ to look like the below:

...
  <link rel="stylesheet" href="{% static'styles.css' %}">
...

The CSS link is obviously not the only static link that you’ll have in your template file. Therefore, make sure you track all those links and update them as illustrated above. Here are some examples:

# for image src
<img src="{% static 'imgs/logo.png' %}">
# for script src
<script src="{% static 'js/app.js' }"></script>

How to Configure & Serve your Django Static Files for Production.

What we have done above will only work during the development of your Django project. When you are about to upload your Django project to Heroku or any other hosting platform, you have to tweak your Django settings even further:

1. Install WhiteNoise & register in settings.py

Whitenoise is a Python library that allows your Django website to serve its own static files in production.

To install it in your Django project, run the following command on your terminal:

(env) $ pip install whitenoise

If you’re using a virtual environment, make sure it is activated.

Now after this, we’ll add Whitenoise to the MIDDLEWARE list in the settings.py file of your Django project:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',

    'whitenoise.middleware.WhiteNoiseMiddleware', #new
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Note that the Whitenoise middleware is below the security middleware but above everything else.

Add STATIC_ROOT & STATICFILES_STORAGE

In our settings.py file, we have two more settings to set in addition to STATIC_URL and STATICFILES_DIRS. If you haven’t set that up yet, please go back to the previous section and see how it’s done.

Let’s start with STATICFILES_STORAGE.

STATICFILES_STORAGE is the file storage engine by which the static files are stored when collecting static files with theΒ collectstaticΒ command which we will look at in the next section. It is by default set to django.contrib.staticfiles.storage.StaticFilesStorage which is provided by Django itself. But since we have migrated to Whitenoise, we can safely use Whitenoise’s storage engine.

Below the STATICFILES_DIRS variable in your settings.py file, write the following code:

STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

Next, let’s look at STATIC_ROOT.

STATIC_ROOT is the folder that all static files will be collected into after you run the collectstatic command.

Below the STATICFILES_STORAGE variable in your settings.py file, write the following code:

STATIC_ROOT = BASE_DIR / "staticfiles"

This means that when the collectstatic command gets run, all static files will be collected into a folder called staticfiles at the root of the project. Calling it staticfiles is the convention for naming this folder that stores our static files. You don’t have to create it manually, it will be created automatically when you run the collectstatic command.

At this point, assuming you’ve been following along since the beginning, a part of your settings.py file should look like this:

STATIC_URL = "/static/"
STATICFILES_DIRS = [BASE_DIR/'static']
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
STATIC_ROOT = BASE_DIR / "staticfiles"

For STATICFILES_DIRS, make sure you add all the paths to all the folders that contain static files because they are going to be collected from there into the STATIC_ROOT.

Django collectstatic

What is Django collectstatic

python manage.py collectstatic is a Django command that is used to collect all static files from the folders specified in STATICFILES_DIRS to the single directory specified in the STATIC_ROOT variable .

This is done because normally, a Django project may have many static file folders and they should be collected in a single location so that they could be served from that one location in a production environment

Even when you know that your Django project has only one static folder, it is best to run the collectstatic command.

Running the Collectstatic command:

In the terminal of your Django project, run the following command:

(env) $ python manage.py collectstatic

After the command runs, your project structure should look something like this:

[project_name]
β”œβ”€β”€ config
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ settings.py
β”‚   β”œβ”€β”€ urls.py
β”‚   └── wsgi.py
...
β”œβ”€β”€ static
β”œβ”€β”€ staticfiles # generated after the collectstatic command
β”œβ”€β”€ templates
└── manage.py

You should see that the staticfiles folder gets generated and inside it, all the other static files of the project.

And that’s it guys, let’s answer some of the frequently asked questions about django collectstatic and static files.

FAQs: Django collectstatic

Do you have to load static in every template Django

No, you only have to load static in template files that have links to static directories. If you load static in the parent template, that will not be applied in child templates. Therefore you’ll also have to load static to child templates as long as they have links to static folders.

How to determine if Django collectstatic is working

After the collectstatic command runs, first, you should check if the staticfiles directory has been generated at the root of your project. Next, check your website to see if your static files are being loaded. And that will show you if Django collectstatic is working.

How does Django know what files are static files?

There are two ways in which Django knows what files are static files. If these files are in a folder called static and this folder is a subfolder of an app folder, then the folder contains static files. If they are in a folder that is referenced in STATICFILES_DIRS in settings.py, then the folder also contains static files.

That’s it for this tutorial. Hope you liked it. And if you did, please share it with fellow Django developers. If you have questions, you’re welcome in the comments section below.

Peace!

Stephen Mclin
Stephen Mclin

Hey, I'm Steve; I write about Python and Django as if I'm teaching myself. CodingGear is sort of like my learning notes, but for all of us. Hope you'll love the content!

Articles: 90