Django Static Files handling explained simply

static_url ,staticfiles_dirs, static_root,staticfiles_storage simply explained in DJango

Django is one of the most powerful Backend Programming languages out there, that makes developers perform their tasks quickly with less weight on them in terms of security, flexibility and scalability of the applications.

Hence one of such ways by which Django encourages the improvement and scalability of the applications is in the management of static files.

What are Static files in Django?

In the context of Django (and other web frameworks), static files refer to the files that remain unchanged during the execution of a web application. These files typically include CSS Stylesheets.css files, JavaScript scripts .js files and images eg jpeg, png files, as well as other assets required to render a web page.

By using these settings such as the STATICFILES_DIRS, STATIC_URL, STATIC_ROOT, and STATICFILES_STORAGE, Django makes it easy to organize and serve static files efficiently, allowing web applications to deliver a better user experience with faster load times and consistent styling and functionality across pages

Let's get down to the settings in the most simple way

Settings are done in the settings.py file of the root directory

settings.py 
....... ### Other codes
STATIC_URL='/static/'
.....

Web development in Django falls under the development stage (where you develop the applications locally on your system) and the production stage (where you push the applications developed to the internet).

As a first approach, Django simply checks this folder to serve static files during development, more so, if you don't specify custom settings for serving static files, Django depends on the settings to serve static files

STATIC_URL = '/static/'

#myproject/
|-- myapp/
|   |-- static/
|   |   |-- css/
|   |   |   |-- style.css
|   |   |-- js/
|   |   |   |-- script.js
|-- myproject/
|   |-- settings.py
|-- manage.py

From the folder structure above, imagine you want to serve the style.css in another DJANGO TEMPLATE HTML file. You follow the reference below

#base.html
#Making reference reference to the style.css
{% load static %} ##This is a must in other to make css files work 
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="{% static 'css/style.css'%}">
    </head>
    <body>
        {% block content %}
        {% endblock content %}
    </body>
</html>

So Django checks the static folder and then calls the css/style.css

What if you had a static/blog/css/style.css, you simply call it thus:

<link rel="stylesheet" type="text/css" href="{% static 'blog/css/style.css'%}">

STATICFILES_DIRS

It's now important we discuss this folder and what it does essentially

#settings.py 
import os 
BASE_DIR = Path(__file__).resolve().parent.parent
....
STATICFILES_DIRS:[
        os.path.join(BASE_DIR,'bootstrap'), #This simply joins the bootstrap folder to the project root
        os.path.join(BASE_DIR, 'myapp1', 'static'),
        os.path.join(BASE_DIR, 'myapp2', 'static'),
]
....

This STATICFILES_DIRS collects all the folders (defined within it) where static files (i.e css etc) are asides from the conventional folder '/static/'

Consider the project structure below :

#myproject/
|-- project/
|   |-- static/
|   |   |-- css/
|   |   |   |-- style.css
|   |   |-- js/
|   |   |   |-- script.js
|-- bootstrap/
|   |-- css/
|   |   |-- bootstrap.min.css
|   |-- js/
|   |   |-- bootstrap.min.js
|-- lovelycss/
|    |--styles/
|    |    |--lovely.css
|-- myproject/
|   |-- settings.py
|-- manage.py

Consider that you want Django to also check the bootstrap and lovelycss folders for CSS and other static files, then that is what staticfiles_dirs is for, you simply define the folders within the staticfiles_dirs in the settings.py as below

#settings.py 
#settings.py 
import os 
BASE_DIR = Path(__file__).resolve().parent.parent
....
STATICFILES_DIRS:[
        os.path.join(BASE_DIR,'bootstrap'), #This simply joins the bootstrap folder to the project root
        os.path.join(BASE_DIR, 'lovelycss','styles'), #Doing this on purpose, so its clear how to call them in a template file

]
....

So the question arises, how do you call the respective .css files of these folders bootstrap and lovelycss in Django Template File, It is shown below :

#base.html
#Making reference reference to the .css in our lovelycss and bootstap
{% load static %} ##This is a must in other to make css files work 
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        #Notice the difference in the calling of the .css files, 
        #you don't repeat the folder names defined in staticfiles_dirs 
        #anymore anymore 
        <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.min.css'%}">
        <link rel="stylesheet" type="text/css" href="{%  static 'styles.css'%}">
    </head>
    <body>
        {% block content %}
        {% endblock content %}
    </body>
</html>

STATIC_ROOT

This setting is primarily needed by Django during production, and it defines the absolute filesystem path to the directory where Django stores all static files for efficient serving during production as the static files are stores in a single location, it is always updated when you run the command python manage.py collectstatic

The static files can then be served efficiently by your web server. which could include Nginx, Apache or even content delivery network (CDN) in a production environment

#settings.py 
#settings.py 
import os 
BASE_DIR = Path(__file__).resolve().parent.parent
....
STATIC_ROOT=str(BASE_DIR.joinpath('static_root'))
#Note that the static_root must be a folder in your project 
#and you can have it as you wish eg staticroot/all/ etc
....

Once you run the python manage.py collectstatic
command, Django will update the content of the static_root itself.

Will my static files structure or content be deleted after running the python manage.py collectstatic command
No! Your static files and their structures will be maintained, and you can continue to use that in your development environment. Django will only update the content of the folder set within the static_root with a consolidated structure of all your static files needed during production to further enhance the scalability and easy loading of your application by the server.

STATICFILES_STORAGE

This is typically an engine that comes in handy and defines how your static files are served during production. It can be handled by Django , but the conventional practice among developers is throw the weight off Django and use other libraries such as whitenoise or others, I will update the content of this variable in the case of the two instances mentioned.

#settings.py
...
#If you decide to use Django which is not the most common practice 
STATICFILES_STORAGE='django.contrib.staticfiles.storage.StaticFilesStorage'
...

In case you decide to use Whitenoise to serve the static files, just update the codes as below after you must have pip install hitenoise or pipenv install whitenoise

#settings.py 
...
INSTALLED_APPS=[
'whitenoise.runserver_nostatic'
]
...
MIDDLEWARE=[
##whitenoise middleware configuration
...
'whitenoise.middleware.WhiteNoiseMiddleware', 
...
]
...
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
...

And there you have the handling of static files in Django communicated in the most basic way, feel free to comment or ask further questions if any and share these with developers who are in the most urgent need of it.

💡
Follow me at @Chasfat_Project and am open to further collaboration.