Difference between static STATIC_URL and STATIC_ROOT on Django
PythonPython 3.xDjangoDjango UrlsDjango StaticfilesPython Problem Overview
I am confused by static root
and want to clarify things.
To serve static files in Django, the following should be in settings.py
and urls.py
:
import os
PROJECT_DIR=os.path.dirname(__file__)
1. Absolute path to the directory in which static files should be collected
STATIC_ROOT= os.path.join(PROJECT_DIR,'static_media/')
2. URL prefix for static files
STATIC_URL = '/static/'
3. Additional locations for static files
STATICFILES_DIRS = ( os.path.join(PROJECT_DIR,'static/'),)
...and in urls.py
the following lines:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += patterns('', (
r'^static/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}
))
python manage.py collectstatic
4. We also use Questions:
-
Could anyone please explain the workflow to me: how should things ideally be done. As of now, I copy/paste the above code snippets into their designated locations and continue making new files in the static directory and it works. In my
settings.STATIC_ROOT
, however, I have pointed to a different directory. -
It would be great if someone could explain the workflow of each setting: how files are collected and managed, and what would be a good practice to follow.
Thanks.
Python Solutions
Solution 1 - Python
STATIC_ROOT
> The absolute path to the directory where ./manage.py collectstatic
will collect static files for deployment.
> Example: STATIC_ROOT="/var/www/example.com/static/"
now the command ./manage.py collectstatic
will copy all the static files(ie in static folder in your apps, static files in all paths) to the directory /var/www/example.com/static/
. now you only need to serve this directory on apache or nginx..etc.
STATIC_URL
> The URL
of which the static files in STATIC_ROOT
directory are served(by Apache or nginx..etc).
> Example: /static/
or http://static.example.com/
If you set STATIC_URL = 'http://static.example.com/'
, then you must serve the STATIC_ROOT
folder (ie "/var/www/example.com/static/"
) by apache or nginx at url 'http://static.example.com/'
(so that you can refer the static file '/var/www/example.com/static/jquery.js'
with 'http://static.example.com/jquery.js'
)
Now in your django-templates, you can refer it by:
{% load static %}
<script src="{% static "jquery.js" %}"></script>
which will render:
<script src="http://static.example.com/jquery.js"></script>
Solution 2 - Python
STATICFILES_DIRS
: You can keep the static files for your project here e.g. the ones used by your templates.
STATIC_ROOT
: leave this empty, when you do manage.py collectstatic
, it will search for all the static files on your system and move them here. Your static file server is supposed to be mapped to this folder wherever it is located. Check it after running collectstatic and you'll find the directory structure django has built.
--------Edit----------------
As pointed out by @DarkCygnus, STATIC_ROOT should point at a directory on your filesystem, the folder should be empty since it will be populated by Django.
> STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
or
> STATIC_ROOT = '/opt/web/project/static_files'
--------End Edit -----------------
STATIC_URL
: '/static/' is usually fine, it's just a prefix for static files.
Solution 3 - Python
All the answers above are helpful but none solved my issue. In my production file, my STATIC_URL was https://<URL>/static
and I used the same STATIC_URL in my dev settings.py file.
This causes a silent failure in django/conf/urls/static.py.
The test elif not settings.DEBUG or '://' in prefix:
picks up the '//' in the URL and does not add the static URL pattern, causing no static files to be found.
It would be thoughtful if Django spit out an error message stating you can't use a http(s)://
with DEBUG = True
I had to change STATIC_URL to be '/static/'
Solution 4 - Python
After Django 3.1+, There is a slight change in the configuration of the directory paths, but the concepts are the same, of course.
STATICFILES_DIRS
STATICFILES_DIRS = [
BASE_DIR / 'static',
BASE_DIR / 'app_1/static',
BASE_DIR / 'app_2/static',
]
As the name suggests, it is a list of directories. It is used for specifying more than one directory for static files. Most useful for the sake of the reusability of an app. Instead of having one directory for all the static files, each app has its independent directory. Just like templates for each individual app.
To configure static files directory of an app:
=> my_app
=> static
=> my_app
=> css
=> js
In development mode, with the command python manage.py runserver
, Django searches for static files using the STATICFILES_FINDERS
setting. By default, it tries to find the requested static file in folders listed in the STATICFILES_DIRS setting. In case of failure, Django tries to find the file using django.contrib.staticfiles.finders.AppDirectoriesFinder
, which looks in the static folder of every installed application in the project.
STATIC_ROOT
STATIC_ROOT = BASE_DIR / 'static'
It is the absolute path to the directory where python manage.py collectstatic
will collect static files for deployment. Example:
/var/www/example.com/static/"
For development, it is not necessary to configure STATIC_ROOT
, but extremely important for production. This is the path to be considered by the Nginx, Apache servers to access the website's static files.
STATIC_URL
URL to use when referring to static files located in STATIC_ROOT. Example: "static/" or "http://static.example.com/"
STATIC_URL = '/static/'
Now, suppose I decide to configure the STATIC_URL='/asset/'
, then I need to change STATIC_ROOT=BASE_DIR / 'asset'
and the name of my directory should also be asset
.
Reference:
https://docs.djangoproject.com/en/4.0/ref/contrib/staticfiles/
Solution 5 - Python
May, 2022 Update:
First of all, I explain about "STATIC_ROOT" then "STATIC_URL".
"STATIC_ROOT" sets the absolute path to the folder where static files used for the apps and admin in a django project are stored and this command below creates the folder and collects static files from the apps and admin in a django project into the folder (*Setting "STATIC_ROOT" never ever influence to static file URL):
python manage.py collectstatic
And "STATIC_ROOT" only works in Production Mode which is "DEBUG = False" as shown below:
# "core/settings.py"
DEBUG = False // Production Mode
Now, we have a django project with the static files "core.js" in "core" folder where "settings.py" is and "myapp.css" in "myapp" folder which is "an app" as shown below:
And "css", "fonts", "img" and "js" folders in "admin" folder in "venv" folder as shown below. *I use Virtual Environment named "venv" for this django project so the static files for "admin" is in it and the relative path to "admin" folder is "venv/lib/python3.8/site-packages/django/contrib/admin/static/admin":
Then, we set "os.path.join(BASE_DIR, 'static')" which is "C:\Users\kai\django-project\static" in Windows in my case to "STATIC_ROOT". In addition, we set "False" to "DEBUG" because "STATIC_ROOT" only works in Production Mode as I said before:
# "core/settings.py"
DEBUG = False // Production Mode
STATIC_ROOT = os.path.join(BASE_DIR, 'static') // Here
STATIC_URL = '/static/'
Now, we run the command below:
python manage.py collectstatic
Then, "static" folder is created and "css", "fonts", "img" and "js" folders in "admin" folder and "myapp.css" in "myapp" folder are collected into "static" folder as shown below but as we can see, "core.js" in "core" folder is not collected into "static" folder as shown below because as I said before, the command "python manage.py collectstatic" collects static files from the apps and admin in a django project but "core" folder which has "settings.py" is not an app and admin. That's why "core.js" in "core" folder is not collected into "static" folder:
But, there is a way to collect "core.js" in "core" folder into "static" folder. To do that, we need to use "STATICFILES_DIRS" then set os.path.join(BASE_DIR, 'core/static')" which is "C:\Users\kai\django-project\core\static" in Windows in my case to "STATICFILES_DIRS" as shown below:
# "core/settings.py"
DEBUG = False
STATICFILES_DIRS = [ // Here
os.path.join(BASE_DIR, 'core/static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
Now again, we run the command below:
python manage.py collectstatic
Then, input "yes" then press "Enter" to overwrite existing "static" folder:
> You have requested to collect static files at the destination location > as specified in your settings: > > C:\Users\kai\django-project\static > > This will overwrite existing files! Are you sure you want to do this? > > Type 'yes' to continue, or 'no' to cancel: yes
Now, "core.js" in "core" folder is collected into "static" folder as shown below:
Next, I explain about "STATIC_URL".
"STATIC_URL" sets the front directory part of static file URL between the host part and the file part of static file URL as shown below (*Setting "STATIC_URL" never ever influence to the absolute path to the folder where static files used for the apps and admin in a django project are stored):
| Host | Directory | File |
| |Front | Back | |
<-------------> <----> <-------> <------>
https://www.example.com/static/admin/css/base.css
For example, we set '/static/' to "STATIC_URL" as shown below (*"STATIC_URL" works in both Development Mode which is "DEBUG = True" and Production Mode which is "DEBUG = False"):
# "core/settings.py"
DEBUG = False
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/' # Here
Then, open Django Admin:
Then, press "F12" to open "Developer Tools" to check the resources used for the currently opened Django Admin page from "Sources" and there are the static files for "admin" which we have just collected into "static" folder:
Then, hover "base.css" in "css" to check the URL:
As we can see, we could set the front directory part "static":
Here
<------>
http://localhost:8000/static/admin/css/base.css
And, this URL below is in this case of "www.example.com" with "https":
Here
<------>
https://www.example.com/static/admin/css/base.css
And, we can change the front directory part "static" to "hello/world".
So, just change "STATIC_URL" from '/static/' to '/hello/world/' as shown below:
# "core/settings.py"
DEBUG = False
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'core/static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/hello/world/' # Here
Then, refresh the Django Admin page:
Then, the front directory part "static" is changed to "hello/world" as shown below:
Here
<----------->
http://localhost:8000/hello/world/admin/css/base.css