163

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}
))

4. We also use python manage.py collectstatic

Questions:

  1. 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.

  2. 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.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
user993563
  • 18,601
  • 10
  • 42
  • 55
  • Could you clarify on what you mean by 'explain the workflow'? also your url patterns should be conditional on if you are developing in part 3. you can do this by adding `if settings.DEBUG:` django is not very good at serving static media, this should be left to a real webserver. – dm03514 Dec 31 '11 at 13:12
  • Hi @user993563 i cant even find the solution in several forum what i want. but your questions explain it clearly thanks man... great job... – Mohideen bin Mohammed Jan 08 '16 at 13:36
  • Good Explanation, Thanks – Ajay Kumar Mar 04 '20 at 07:15

5 Answers5

109

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>
suhailvs
  • 20,182
  • 14
  • 100
  • 98
  • 1
    Whats the dfference between your example and this: href="{% static "jquery.js" %}" – User Jun 28 '14 at 23:29
  • 8
    @macdonjo both `{{ STATIC_URL }}jquery.js` and `{% static "jquery.js" %}` are same. ie both will return `/static/jquery.js`. [Newer django](https://docs.djangoproject.com/en/dev/howto/static-files/) versions recommend to use `{% static "jquery.js" %}`, but you need to load the templatetag, ie `{% load staticfiles %}`. in [older django](https://docs.djangoproject.com/en/1.4/howto/static-files/) version recommends `{{STATIC_URL}}` – suhailvs Jun 29 '14 at 12:05
  • I see. I was trying to find a bug that caused most of my templates to load my stylesheet except one page. I changed it over to `static` method instead of `STATIC_URL` method, and the bug was gone. Good call on the suggestions based on versions. – User Jun 29 '14 at 15:08
  • But as I just tried and found out that I can set `STATIC_URL = '/static/abcd/'`, basically just an arbitrary path and Django still correctly fetches static files. For example, it is serving a CSS file from `` as seen in the DevTools although there is no such directory on my system. My CSS file is in `common_static/css/app.css` and is collected to `static/css/app.css`. So this threw a really big wrench into my understanding of how STATIC_URL works. How is this possible? – ruslaniv Feb 24 '21 at 17:46
  • @RusI `STATIC_URL` is the url Django creates, it is not a directory. – suhailvs Feb 25 '21 at 00:54
  • Yes, I understand that, but it still has to point to en existing resource, right? In my case it's pointing to an invalid resource but it still works. – ruslaniv Feb 25 '21 at 06:33
  • `` will actually render with domain name appended, like ``. you must ensure the file is served in `https://www.example.com/static/abcd/css/app.css` – suhailvs Feb 25 '21 at 13:48
42

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.

keni
  • 1,730
  • 13
  • 19
  • 3
    Here, the link to static file management in 1.3 https://docs.djangoproject.com/en/1.3/howto/static-files/ – keni Dec 31 '11 at 19:12
  • 2
    `STATICFILES_DIRS` should serve as additional dirs for static files.If you put all your css/js/images into the APP_NAME/static/APP_NAME folder,then there is no need to specify `STATICFILES_DIRS`. – laike9m Aug 19 '13 at 11:34
  • Thanks for the answer, about the leaving empty the STATIC_ROOT, I actually had to specify it in `settings.py` (by doing `STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')`) before running the collectstatic command. – DarkCygnus Apr 18 '18 at 00:21
  • Hmm, I can see how easily this can be misleading. What I mean by leaving it empty is that is usually starts out empty, no files in it. I will update the answer to remove the confusion. – keni Apr 18 '18 at 13:33
7

Aug, 2023 Update:

First of all, I explain about STATIC_ROOT, then [STATIC_URL2.

<STATIC_ROOT>

STATIC_ROOT can set a folder path and be used with the command below which collects the static files of the apps and admin in a Django project into the folder path. *STATIC_ROOT never ever influence to STATIC_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:

enter image description here

And css, fonts, img and js folders in admin folder in venv folder as shown below. *I use the 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/:

enter image description here

Then, we set BASE_DIR / 'static/' which is C:\Users\kai\django-project\static on Windows in my case to STATIC_ROOT. In addition, we set DEBUG = False because STATIC_ROOT only works in Production Mode as I said before:

# "core/settings.py"

DEBUG = False // Production Mode

STATIC_ROOT = 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:

enter image description here

But, there is a way to collect core.js in core folder into static folder. To do that, we need to set BASE_DIR / 'core/static/' which is C:\Users\kai\django-project\core\static on Windows in my case to STATICFILES_DIRS in settings.py as shown below:

# "core/settings.py"

DEBUG = False

STATICFILES_DIRS = [ # Here
    BASE_DIR / 'core/static/'
]

STATIC_ROOT = BASE_DIR / 'static/'
STATIC_URL = 'static/'

Or, we need to set core to INSTALLED_APPS in settings.py as shown below:

# "core/settings.py"

DEBUG = False

INSTALLED_APPS = [
    'core', # Here
]

Now again, we run the command below:

python manage.py collectstatic 

Then, input yes then press Enter to overwrite the 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:

enter image description here

<STATIC_URL>

Next, I explain about STATIC_URL.

STATIC_URL can set the front directory part of static file URL between the host part and the file part of static file URL as shown below. *STATIC_URL never ever influence STATIC_ROOT:

       |     Host      |   Directory    |  File  |
       |               |Front |  Back   |        |
        <-------------> <----> <-------> <------>      
https://www.example.com/static/admin/css/base.css

For example, we set 'static/' to STATIC_URL in settings.py 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 = [
    BASE_DIR / 'core/static/'
]

STATIC_ROOT = BASE_DIR / 'static/'
STATIC_URL = 'static/' # Here

Then, open Django Admin:

enter image description here

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:

enter image description here

Then, hover base.css in css to check the URL:

enter image description here

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 = [
    BASE_DIR / 'core/static/'
]

STATIC_ROOT = BASE_DIR / 'static/'
STATIC_URL = 'hello/world/' # Here

Then, refresh the Django Admin page:

enter image description here

Then, the front directory part static is changed to hello/world as shown below:

                         Here  
                     <----------->
http://localhost:8000/hello/world/admin/css/base.css
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
3

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/'

MIkee
  • 904
  • 8
  • 12
0

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/

rs_punia
  • 421
  • 2
  • 6
  • 17