How To Handle Static Files in Django

by Applied Informatics

Websites generally need to serve files such as images, JavaScript, or CSS in addition to html. In Django, we refer to these files as “static files”. Django provides django.contrib.staticfiles to help you manage them. Serving static files, especially during development, is frequently a pain point. Let’s start with development when you have DEBUG = True. We will create a Django project from scratch so that we are fully aware of which file in which directory we are talking about.

Setting Up Project

We will try everything inside a virtual environment. We name our virtual environment as staticvirt. So the command we need is,

~$ virtualenv staticvirt
~$ cd staticvirt/
~/staticvirt$ source bin/activate
(staticvirt)~/staticvirt$ pip install django
  • Start a Django project.
~$ django-admin.py startproject test_project
  • Change to directory containing the project.
~$ cd test_project/
  • Let’s see the directory structure at this point.
(staticvirt)~/staticvirt/test_project$ tree
 .
 |-- manage.py
 `-- test_project
 |-- __init__.py
 |-- settings.py
 |-- urls.py
 `-- wsgi.py

1 directory, 5 files

  • Check contents of test_project/settings.py. Search for all lines which contain the substring static. I will list all those lines below.
STATIC_ROOT = ''

STATIC_URL = '/static/'

STATICFILES_DIRS = (
)

STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

INSTALLED_APPS = (
....
....
'django.contrib.staticfiles',
....
)

Whatever we saw till here is the default setting provided to us by Django. We have not made any modifications.

Let’s create an app in which we will have a template and then we will write a static file, which will be a stylesheet, and will use that stylesheet in this template. Type

python manage.py startapp some_app
Add some_app to INSTALLED_APPS in test_project/settings.py.

We need a urls.py file for some_app where we will define the urls available on some_app. Project’s urls.py should include urls.py of some_app. So, we add the following line to test_project/urls.py.

url(r'^some_app/', include('some_app.urls'))

We have following line in urls.py of some_app i.e in some_app/urls.py.

url(r'^home$', direct_to_template, {"template": "some_app/home.html"})

Create a directory called templates and add it to TEMPLATE_DIRS. I created this template directory on the same level as manage.py.

Adding templates directory to TEMPLATE_DIRS require following changes.

PROJECT_DIR = os.path.dirname(__file__)
TEMPLATE_DIRS = (
 os.path.join(PROJECT_DIR, '../templates'),
 )

We need to create home.html for app some_app and it needs to go into templates. So, we create a template file templates/some_app/home.html. We have the following content in the html file.

<html>
<body>
<h1>This is home for some_app</h1>
</body>
</html>

Let’s check our project directory structure, so as to remove any confusion.

~/staticvirt/test_project$ tree -I *.pyc
.
|-- manage.py
|-- some_app
| |-- __init__.py
| |-- models.py
| |-- tests.py
| |-- urls.py
| `-- views.py
|-- templates
| `-- some_app
| `-- home.html
`-- test_project
|-- __init__.py
|-- settings.py
|-- urls.py
`-- wsgi.py

4 directories, 11 files

We did not want .pyc files to be shown and so used a switch with tree to ignore .pyc files.

Start the server. Make sure you have added your database settings.

(staticvirt)~/staticvirt/test_project$ python manage.py runserver

Navigate to http://127.0.0.1:8000/some_app/home. Hereafter, we will call this page as home page of some_app. You should see html we just wrote.

  • Serving static files.

Let’s edit home.html of some_app and add a stylesheet to it. There doesn’t exist any stylesheet yet, we will create it after editing html.

<html>
<head>
<link href=”{{STATIC_URL}}styles.css” rel=”stylesheet” type=”text/css”>
</head>
<body>
<h1>This is home for some_app</h1>
</body>
</html>

Refresh home page of some_app. You will not see any changes yet because we have not created stylesheet file.

Also navigate to http://127.0.0.1:8000/static/styles.css, you will see a 404 page.

Static files should be created inside static/ subdirectory of apps

Let’s create stylesheet file. Since we want to use this stylesheet in the template of some_app, we will create it inside static/ subdirectory of some_app. So, let’s create a file some_app/static/styles.css. Add following contents to this file.

body
{
background-color: red;
}

Refresh home page of some_app. You should see that the background of this page becomes red. Also, refresh page at http://127.0.0.1:8000/static/styles.css. You will see that it’s no more a 404 page and you will see contents of your stylesheet at this url. If you can’t see these changes, make sure that some_app is added to INSTALLED_APPS and restart the server.

About STATIC_ROOT

You should never require STATIC_ROOT in development if you are using Django’s runserver.
Once you go to production, you can use it on the server. Django provides a management command called collectstatic, which will collect all the static resources, i.e the resources found in STATICFILES_DIRS and the resources found in static/ subdirectory of apps, into a single location defined by STATIC_ROOT.
STATIC_ROOT only comes into picture if you want to use collectstatic management command provided by Django.

Points to be noted

We did not make any changes to any  static settings provided by Django. We left static settings as they were in default settings.py provided by Django.

You don’t need any change in your urls.py for serving your static files in development. You don’t need to add staticfiles_urlpatterns().

How it works Internally

First, check all static settings we have in settings.py.

They are STATIC_URL, STATIC_ROOT, STATICFILES_FINDERS, STATICFILES_DIRS.
Also, we have ‘django.contrib.staticfiles’ in INSTALLED_APPS.
For now, forget about STATIC_ROOT and STATICFILES_DIRS. Even if you comment it or delete it from settings, your project will continue to work as it is working currently.
We need ‘django.contrib.staticfiles’ in our INSTALLED_APPS if we want Django’s default server to serve static files.
By Django’s default server, we mean python manage.py runserver, that’s provided with Django.
Django’s default server will serve the static files at STATIC_URL. Notice that STATIC_URL is set to ‘/static/’.

That’s why we have our static file, ie stylesheet, getting served at http://127.0.0.1:8000/static/styles.css. If you try to get it at http://127.0.0.1:8000/static_changed/styles.css, you will not be able to, you will get a 404 instead.

If you want to get the stylesheet at http://127.0.0.1:8000/static_changed/styles.css, make STATIC_URL=’/static_changed/’. Go ahead make this change and check. With this change, static files will get served at /static_changed/.

This change was only to illustrate what is the purpose of STATIC_URL. Change it back to its default, i.e STATIC_URL=’/static/’.

 

To learn more about

Contact Us




  


  


Leave a Reply

Your email address will not be published. Required fields are marked *

Tools & Practices

Tools and Technologies we use at Applied

Contact us now

Popular Posts