Serving Static Files In Django

Sitikanta Panigrahi
7 min readFeb 21, 2021

--

What Are Static Files?

Static files are files that don’t change when your application is running.

These files do a lot to improve your application, but they aren’t dynamically generated by your Python web server. In a typical web application, your most common static files will be the following types:

  • Cascading Style Sheets, CSS
  • JavaScript
  • Images

Keep in mind that even though Django will serve these files statically, there may be a complex process in place to produce the files. For instance, modern JavaScript apps often have complex processes using JavaScript build tools like webpack to build the final JavaScript files that are served to users.

Static files are crucial to your Django project because the modern web requires more than dynamically generated HTML markup. Do you visit any website that has zero styling of its HTML? These kinds of sites exist and can be awesome for making a quick tool, but most users expect websites to be aesthetically pleasing. For us, that means that we should be prepared to include some CSS styling at a minimum.

Let’s look at some configuration to see where static files live in your project, then begin to work with some examples.

Configuration

To use static files in your project, you need the django.contrib.staticfiles app in your project’s INSTALLED_APPS list. This is another one of the default Django applications that Django will include if you start from the startproject command.

The staticfiles app has a handful of settings that we need to consider to start.

I’m going to make the same recommendation about static files as I did with templates. I recommend that you create a static directory at the root of your project to hold your static files. Similarly to templates, the staticfiles app will look for static directories within each of your Django apps to find files, but I find it easier to work with and locate static files if they are all in the same directory.

To make that setup work, use the STATICFILES_DIRS setting. This setting tells Django any additional locations for static files beyond looking for a static directory within each app.

Next, we can define the URL path prefix that Django will use when it serves a static file. Let’s says you have site.css in the root of your project’s static directory. You probably wouldn’t want the file to be accessible as mysite.com/site.css. To do so would mean that static files could conflict with URL paths that your app might need to direct to a view.

With STATIC_URL set, we can access site.css from mysite.com/static/site.css.

There’s one more crucial setting that we need to set, and it is called STATIC_ROOT. When we deploy our Django project, Django wants to find all static files from a single directory. The reason for this is for efficiency. It’s possible for Django to search through all the app static directories and any directories set in STATICFILES_DIRS whenever it searches for a file to serve, but that would be slow.

Instead, Django will put all static files into a single directory so that searching for a file is a search through a single file tree. We’ll look more at how this happens in the deployment section later in this article.

Once we set STATIC_ROOT, Django will have the desired output location for static files. If you set the path somewhere in your repository, don’t forget to put that path in your .gitignore if you’re using version control with Git (and I highly recommend that you do!). I happen to set my STATIC_ROOT to a staticfiles directory.

Now that we know how to configure static files, we’re ready to see how to use them in our Django code.

Working With Static Files

The primary way of working with static files is with a template tag. The static template tag will help render the proper URL for a static file for your site.

Here’s an example template to consider:

In this example, I’m assuming that there is a css directory in my static directory with a site.css file inside. Django will render this template tag as /static/css/site.css in the most basic format. We should also note that I had to include {% load static %} to ensure that the static template tag was available.

In practice, I find that this load requirement bites me all the time. Thankfully, the TemplateSyntaxError that Django will raise provides a good clue on how to fix this issue. The exception says “Did you forget to register or load this tag?” How helpful of the Django developers to tell us what we’re probably missing!

Since we know that STATIC_URL is /static/ from the configuration section, why don’t I hardcode the link tag path to /static/css/site.css? You could, and that might work, but you’ll probably run into some long term problems.

  • What if you ever wanted to change STATIC_URL? Maybe you want to change it to something shorter like /s/. If you hardcode the name, now you have more than one place to change.
  • Using some extra features, Django may change the name of a file to something unique by adding a hash to the file name. With a hardcoded path of /static/css/site.css, this may lead to a 404 response if Django expects the unique name instead. We’ll see what the unique name is for in the next section.

We should remember to use the static tag in the same way that we use the url tag when we want to resolve a Django URL path. Both of these tags help avoid hardcoding paths that can change.

Less commonly, we can refer to a static file from Python code. You can do this by calling a static function defined in the same location as the static template tag function, but the function is not located where you might expect it. Instead of importing from the staticfiles app, Django defines these functions in django.templatetags.static.

For example, if you wanted to serve a JSON view that feeds a JavaScript client application the path to a CSS file, you might write:

Deployment Considerations

In the configuration section, we saw the STATIC_ROOT option. That option will collect all the static files into a single directory, but when does it do that? And how do static files work when we run in development mode and don’t have all the files in the STATIC_ROOT location?

When you deploy your application to a server, one crucial setting to disable is the DEBUG setting. If DEBUG is on, all kinds of secret data can leak from your application, so the Django developers expect DEBUG to be False for your live site. Because of this expectation, certain parts of Django behave differently when DEBUG changes, and the staticfiles app is one such part.

When DEBUG is True and you are using the runserver command to run the development web server, Django will search for files using a set of “finders” whenever a user requests a static file. These finders are defined by the STATICFILES_FINDERS setting, which defaults to:

As you might guess, the FileSystemFinder looks for any static files found in the file system directory that we listed in STATICFILES_DIRS. The AppDirectoriesFinder looks for static files in the static directory of each Django application that you have. You can see how this gets slow when you realize that Django will walk through len(STATICFILES_DIRS) + len(INSTALLED_APPS) before giving up to find a single file.

To make this whole process faster, we turn DEBUG to False. When DEBUG is False, all of the slow machinery that searches for files throughout your project for static file requests is turned off. Django only looks in the STATIC_ROOT directory for files.

Since the finders are off when DEBUG is True, we have to make sure that STATIC_ROOT is filled with all the proper files. To put all the static files into place, you can use the collectstatic command.

collectstatic will copy all the files it discovers from iterating through each finder and collecting files from what a finder lists. In my example below, my Django project directory is myproject, and I set STATIC_ROOT to staticfiles.

When deploying your application to your server, you would run collectstatic before starting the web server. By doing that, you ensure that the web server can access any static files that the Django app might request.

For more information check this article .

I will post the deployment process of static files in cloud storages in later tutorials.

Happy reading..

--

--

Sitikanta Panigrahi

A Web Developer by passion.Knows something about Django,Python and JavaScript