Django Static Files

Django Static Files

So far we have not seen any Cascading Style Sheets, JavaScript code, or Image files in our simple Django app. These types of files are referred to as static files. These types of files don’t typically change, therefore we refer to them as static. The templates that we have been working with do change since there is logic inside of them and they output data conditionally based on that logic. Every website or application is going to need a certain number of static files to support it and that is what we will learn about now.


App Specific Static Files

In the app folder, we can add a new folder named static.

django static files in app

Now inside of the static folder, we should create another folder with the same name as the app. We are following the same exact convention we used when creating the templates folder.

static files app name folder

Inside of this folder, we could add folders for images, CSS, and JavaScript like so.

css js image static files django


Reviewing settings.py For Static Files

By default, you should not have to make any changes in the settings.py file but helps to understand how static files are supported in Django. In the INSTALLED_APPS list in settings.py there should be a line that reads django.contrib.staticfiles like we see below.

INSTALLED_APPS = [
    'goals',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

This is required by Django to turn on the functionality needed to work with static files. Towards the end of settings.py, you will see a line that looks like this:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = '/static/'

This setting does not deal with where you can store static files, but rather where they are served. The default setting is /static/ so that means the URL that would serve static files might begin at something that looks like https://myproject.com/static/. You don’t need to change anything here. Django already knows to look for a static folder inside of any app folders for the project.


Adding style.css

We can now add a CSS file into the css folder and give it a name. We’ll simply call it style.css.

css static file django

Inside of that style.css file, we can add some basic CSS Styling.

ul {
  list-style: square;
  outline: solid red 5px;
  padding: 20px;
}

li {
  color: green;
  font-size: 20px;
  padding: 5px;
}

a:visited {
  color: blue;
}

{% load static %}

Including static files in your templates are now a two-step process. The first step is to call the {% load static %} directive at the top of the file. We are calling in our base.html template file and what it does is load some additional functionality like a plugin.

{% load static %}
<!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" />
    <title>{% block title %} Hello World {% endblock title %}</title>
  </head>
  <body>
    {% block content %}{% endblock content %}
  </body>
</html>

{% static %}

The second step to including a static file in a Django template is to call the {% static %} plugin while providing it a path to the file in question. We now have a style.css file that we would like to use. To access it we can use {% static ‘goals/css/style.css’ %} like so:

{% load static %}
<!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="{% static 'goals/css/style.css' %}" />
    <title>{% block title %} Hello World {% endblock title %}</title>
  </head>
  <body>
    {% block content %}{% endblock content %}
  </body>
</html>

At this point, the website should load with our new style.css file included.

django css static file


Project (Global) Static Files

It is entirely possible to set up static files for use in the entire project, not just on a per-app basis. The process is similar and we can add a new static folder at the project level to begin.

django global static files

We’ll also set up the related images, css, and js subfolders inside of the static folder like so.

global static files

Finally, let’s add a global.css file into the css subfolder like so.

css for entire django project

To test out this global CSS we’ll just change up the font a bit like so:

static\css\global.css

* {
    font-family:Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif
}

Global static settings.py

Django already knows how to look for static files on a per-app basis as we discussed above. It does not know how to find static files at the Project or Global level without some configuration being performed on your part. To make Django aware of your static folder at the project level, we can update settings.py by adding the highlighted code shown.

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    BASE_DIR / 'static'
]

To include this CSS globally, we use {% static ‘css/global.css’ %} in the base.html file. Note, we have removed the original CSS since that should be at an app-level only.

{% load static %}
<!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="{% static 'css/global.css' %}" />
    <title>{% block title %} Hello World {% endblock title %}</title>
  </head>
  <body>
    {% block content %}{% endblock content %}
  </body>
</html>

django global css styles

To keep static files that should be associated only with a particular app we can use the familiar block content paradigm.

templates\base.html

{% load static %}
<!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="{% static 'css/global.css' %}" />
    {% block css %}{% endblock css %}
    <title>{% block title %} Hello World {% endblock title %}</title>
  </head>
  <body>
    {% block content %}{% endblock content %}
  </body>
</html>

goals\templates\goals\index.html

{% extends 'base.html' %} 

{% load static %}

{% block css %}
<link rel="stylesheet" href="{% static 'goals/css/style.css' %}"/>
{% endblock css %}

{% block title %}Goals{% endblock title %} 

{% block content %}
<ul>
  {% for timeframe in timeframes reversed %} {% if timeframe == 'monthly' %}
  <li><a href="{% url 'namedurl' timeframe %}">{{ timeframe|upper }}</a></li>
  {% else %}
  <li><a href="{% url 'namedurl' timeframe %}">{{ timeframe|capfirst }}</a></li>
  {% endif %} {% endfor %}
</ul>
{% endblock content %}

Excellent! We are now serving app-specific static files which we can see by the funky red outline and square list properties. We are also serving global static files as we can see by the Impact font that is present on the page.

app static files and global static files together

Learn More About Static Files In Django