New to Django and confused about how to handle templates and static files? Don't worry, you are in good company. Many people get confused by this at some point.

Here is a quick example of how to handle your static files and templates in Django 1.8.

1   Settings

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

STATIC_URL = '/static/'

2   Directory layout

mysite  # The top-level directory
├── manage.py
├── mysite  # The project directory
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── polls  # An app
    ├── __init__.py
    ├── admin.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

mysite is the project. polls is an app.

polls should be listed in the INSTALLED_APPS setting. mysite is not listed their by default.

3   Templates

So, how do you handle your templates? Here it is:

  1. Change this line in your settings.py:
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'mysite', 'templates'],
        ...
    },
]
  1. Your filesystem tree should look like this:
mysite
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── templates  # project-specific templates
│   │   ├── base.html # project-specific base template
│   ├── urls.py
│   └── wsgi.py
└── polls
    ├── __init__.py
    ├── admin.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── templates  # templates for the polls app
    │   └── polls
    │       └── poll.html
    ├── tests.py
    └── views.py

That way, you can override any app-specific template. Simply create the corresponding template in your project dir. It will override the template from the app.

mysite
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── templates
│   │   ├── base.html
│   │   └── polls
│   │       └── poll.html
│   ├── urls.py
│   └── wsgi.py
└── polls
    ├── __init__.py
    ├── admin.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── templates
    │   └── polls
    │       └── poll.html
    ├── tests.py
    └── views.py

Here, the poll.html template from the mysite/templates/polls directory will take precedence over the template from polls/templates/polls.

In your views, you reference your templates like this:

render(request, 'polls/poll.html')

Within an app template, you may inherit from the project-wide base template:

{% extends "base.html" %}

4   Static files

For static files, you do something very similar to templates. In settings.py:

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "mysite", "static"),
)
myproject
├── manage.py
├── myproject
│   ├── __init__.py
│   ├── settings.py
│   ├── static  # project-specific static files
│   │   └── project.css
│   │   └── polls
│   │       └── polls.css  # override polls.css from the polls app
│   ├── templates
│   │   ├── base.html
│   ├── urls.py
│   └── wsgi.py
└── polls
    ├── __init__.py
    ├── admin.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── static  # app-specific static files
    │   └── polls
    │       └── polls.css
    ├── templates  # app-specific templates
    │   └── polls
    │       └── poll.html
    ├── tests.py
    └── views.py

You reference your static files in your templates like this:

{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'project.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'polls/polls.css' %}">

5   Static files on production

In your settings:

STATIC_ROOT = '/some/directory'

Configure your webserver so serve files from this directory.

Run manage.py collectstatic when deploying.

6   An alternative approach

You can also put your project into INSTALLED_APPS. If you do that, there is no need to change the TEMPLATES and STATICFILES_DIRS settings. However, beware that the order of INSTALLED_APPS matters. The app that is listed first will take precedence.