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.
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.
Inside of this folder, we could add folders for images, CSS, and JavaScript like so.
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.
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.
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.
We’ll also set up the related images, css, and js subfolders inside of the static folder like so.
Finally, let’s add a global.css file into the css subfolder like so.
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>
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.
Learn More About Static Files In Django
- How to Static Files (docs.djangoproject.com)
- Working With Django Templates Static Files (digitalocean.com)
- Django Static Files Tutorial (dev.to)
- Django Static Files Handling (data-flair.training)
- Django Static Files (javatpoint.com)
- Python Django Static Files Templates How To (kite.com)
- Django staticfiles (help.pythonanywhere.com)
- Tutorials Django Static Files (learndjango.com)
- Serving Static Files On Django Production Tutorial (stackoverflow.com)
- Django Static Files And Images (vegibit.com)