Dec 02, 2025
Andzelika D. & Ariffud M.
5min Read
In Django, static files are the non-dynamic assets that shape your web application’s front end, including CSS, JavaScript, and images.
You need to manage static files carefully because Django treats them differently in development and production environments.
Configuring and serving Django static files involves four key stages:
You configure static files in Django through the settings.py file. In it, you define key parameters that tell Django where to find and how to serve your assets.
In development, you mainly configure two settings: STATIC_URL and STATICFILES_DIRS.
Add the following to your project_name/settings.py file:
# project_name/settings.py
# URL prefix for static files.
# Example: '/static/css/style.css'
STATIC_URL = '/static/'
# Additional directories Django will search for static files,
# in addition to each app's 'static' folder.
STATICFILES_DIRS = [
BASE_DIR / "static",
]By default, Django looks for static files inside a static folder within each app directory. This approach keeps every app’s assets organized and self-contained.
A good practice is to create a subdirectory inside static named after the app itself. Doing so prevents filename conflicts when multiple apps include assets with the same name, such as style.css.
Here’s an example structure:
my_app/ ├── __init__.py ├── models.py ├── static/ │ └── my_app/ │ ├── style.css │ └── main.js └── views.py
After configuring and organizing your static files, use them in your Django templates to load stylesheets, scripts, and images.
To use static files in Django templates, load the static template tag library and use the {% static %} tag to generate the correct URL for each asset.
Place the {% load static %} tag at the top of any template that references static assets. This makes the {% static %} tag available in that template.
{% load static %}
<!DOCTYPE html>
<html>After loading the static tag library, link your CSS, JavaScript, and image files with the {% static %} tag. This tag takes the asset’s relative path and generates the full URL based on your STATIC_URL setting.
Here’s an example using the my_app structure:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
<link rel="stylesheet" href="{% static 'my_app/style.css' %}">
</head>
<body>
<h1>Welcome!</h1>
<img src="{% static 'my_app/images/logo.png' %}" alt="Logo">
<script src="{% static 'my_app/main.js' %}"></script>
</body>
</html>The next step is to prepare your static files for deployment so Django can serve them efficiently in production.
In a production environment where DEBUG is set to False, Django’s development server stops serving static files.
Therefore, you must collect all project static assets into a single directory that your web server can access. The django.contrib.staticfiles app, included in INSTALLED_APPS by default, handles this process.
The STATIC_ROOT setting defines the directory where Django collects all static files from your project and its apps for deployment.
Don’t confuse STATIC_ROOT with STATICFILES_DIRS:
Add this line to your project_name/settings.py file:
# project_name/settings.py # Absolute path to the directory where collectstatic gathers static files for deployment. STATIC_ROOT = BASE_DIR / "staticfiles"
Use the python manage.py collectstatic command to gather all static files from your STATICFILES_DIRS and app directories, then copy them into the folder defined by STATIC_ROOT.
Run the following command in your terminal:
python manage.py collectstatic
Django will prompt you to confirm, then copy the files and create the staticfiles directory if it doesn’t exist.
While collectstatic prepares your files for production, Django also provides built-in tools for serving static files during development.
In production, configure a dedicated web server such as Nginx or Apache to serve static files directly from the STATIC_ROOT directory.
This setup improves efficiency by letting your Django application server handle dynamic requests while the web server delivers static assets.
A typical Nginx setup uses a location block to intercept requests for static files and serve them directly from the filesystem. Nginx forwards all other requests to your Django application.
Here’s a basic server block configuration:
server {
listen 80;
server_name your-domain.tld;
# Serve static files
location /static/ {
alias /path/to/your/project/staticfiles/;
}
# Forward requests to Django app
location / {
proxy_pass http://127.0.0.1:8000; # Gunicorn running on port 8000
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}In this example, Nginx serves any request starting with /static/ directly from the staticfiles directory, while forwarding all other requests to your Django app.
A content delivery network (CDN) offers an even faster way to serve static assets. By delivering files from servers closer to your users, a CDN improves performance and reduces load on your application server.
To use a CDN:
# settings.py STATIC_URL = "https://your-cdn-provider.com/static/"
Once configured, the {% static %} tag generates URLs that point to your CDN, speeding up delivery of your site’s assets.
With your static files served through a web server or CDN, you can optimize them further to improve loading speed and overall performance.
To improve your application’s front-end performance, add caching and file versioning to your static assets.
You can tell browsers to cache your static files by adding caching headers in your web server configuration. This lets the browser store a local copy of the files for a set time, avoiding unnecessary downloads on repeat visits.
In Nginx, add the expires and add_header directives inside your static location block:
location /static/ {
alias /path/to/your/project/staticfiles/;
expires 30d;
add_header Cache-Control "public, no-transform";
}Long-term browser caching creates a problem when you update a file: users may still load the old cached version. Django solves this with a technique called cache-busting.
When you enable ManifestStaticFilesStorage, Django renames each static file with a hash of its content during the collectstatic process. For example, style.css becomes style.a1b2c3d4.css.
Because the filename changes whenever the content does, the browser must download the new version.
To enable ManifestStaticFilesStorage, update the STORAGES dictionary in your settings.py file. This setting tells Django to use ManifestStaticFilesStorage for static files.
# settings.py
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
},
}This configuration makes collectstatic rename each file by appending a hash of its content, enabling effective cache-busting. Django still uses the default key for general file storage operations.
In addition to optimizing your own assets, you’ll often need to include third-party static libraries in your Django project.
You can integrate third-party front-end libraries such as Bootstrap or jQuery into your Django project with just a few steps. The process works the same for any library.
{% load static %}
<link rel="stylesheet" href="{% static 'vendor/bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
Now that you understand how to manage static assets, the next step is learning how Django handles application data and user authentication.
A key part of this is customizing the Django user model. Doing so lets you extend the default user schema to fit your project’s needs.
Getting this structure right is crucial, since it directly affects how you implement features like user profiles, permissions, and personalized content.