102

I'm following this tutorial on a Windows 7 environment.

My settings file has this definition:

TEMPLATE_DIRS = (
    'C:/django-project/myapp/mytemplates/admin'
)

I got the base_template from the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into an admin subdirectory of myapp directory as the tutorial instructed, but it doesn't seem to take affect for some reason.

Any clue of what might be the problem?

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
shaytac
  • 3,789
  • 9
  • 36
  • 44

14 Answers14

206

I know this isn't in the Django tutorial, and shame on them, but it's better to set up relative paths for your path variables. You can set it up like so:

import os.path

PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))

...

MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media/')

TEMPLATE_DIRS = [
    os.path.join(PROJECT_PATH, 'templates/'),
]

This way you can move your Django project and your path roots will update automatically. This is useful when you're setting up your production server.

Second, there's something suspect to your TEMPLATE_DIRS path. It should point to the root of your template directory. Also, it should also end in a trailing /.

I'm just going to guess here that the .../admin/ directory is not your template root. If you still want to write absolute paths you should take out the reference to the admin template directory.

TEMPLATE_DIRS = [
    'C:/django-project/myapp/mytemplates/',
]

With that being said, the template loaders by default should be set up to recursively traverse into your app directories to locate template files.

TEMPLATE_LOADERS = [
    'django.template.loaders.filesystem.load_template_source',
    'django.template.loaders.app_directories.load_template_source',
    # 'django.template.loaders.eggs.load_template_source',
]

You shouldn't need to copy over the admin templates unless if you specifically want to overwrite something.

You will have to run a syncdb if you haven't run it yet. You'll also need to statically server your media files if you're hosting django through runserver.

bignose
  • 30,281
  • 14
  • 77
  • 110
digitaldreamer
  • 52,552
  • 5
  • 33
  • 28
  • 1
    thanks alot removing "/admin" at the end of the TEMPLATE_DIRS relative path did it. – shaytac Jun 14 '10 at 17:30
  • 1
    This suggestion puts the templates directory inside the project folder. For better organization, does it make more sense to put it inside an app's folder instead? – Sahas Katta Jun 02 '12 at 00:06
  • 2
    This fixed my problem. Thanks. BUT, the default settings file had a comment with TEMPLATE_DIRS saying, "Don't forget to use absolute paths, not relative paths." Does anyone know the justification for that comment? – bhekman Mar 19 '13 at 04:58
  • 1
    PROJECT_PATH is the absolute path of the project folder. This method sets the absolute media path dynamically at runtime so the value isn't hard coded and can change automatically with the location of the project. This is an old post but you can use this to define the location of any folder or file in the project. – digitaldreamer Mar 19 '13 at 20:23
  • 1
    In a typical project, the templates folder is a *peer* to the project folder (along with all the applications). When this is the case, change to `TEMPLATE_DIRS = os.path.realpath(PROJECT_DIR + '../templages')` – Uri London Apr 10 '13 at 04:43
  • 2
    I would suggest using `os.path.join` to append paths to the base dir. – antonagestam Dec 30 '17 at 16:25
  • 1
    `TEMPLATE_DIRS` has been removed since Django 1.10: https://docs.djangoproject.com/en/dev/internals/deprecation/#deprecation-removed-in-1-10 – Zhe Feb 13 '22 at 15:49
42

If using Django settings as installed, then why not just use its baked-in, predefined BASE_DIR and TEMPLATES? In the pip installed Django(v1.8), I get:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            ### ADD YOUR DIRECTORY HERE LIKE SO:
            BASE_DIR + '/templates/',
        ],
        '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',
            ],
        },
    },
]
NathanQ
  • 1,024
  • 18
  • 20
  • 1
    this «BASE_DIR + '/templates/',» did the trick. And it looks way more elegant, rather than separate section, too. – Maxiller Jun 23 '19 at 18:20
  • 4
    use `os.path.join(BASE_DIR, 'templates')` for the path to be platform independent. – Abhyudai Mar 16 '20 at 15:45
15

Smart solution in Django 2.0.3 for keeping templates in project directory (/root/templates/app_name):

settings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMP_DIR = os.path.join(BASE_DIR, 'templates')
...
TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [TEMP_DIR],
...

in views.py just add such template path:

app_name/html_name
2RMalinowski
  • 357
  • 5
  • 3
9

For Django 1.6.6:

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

Also static and media for debug and production mode:

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
if DEBUG:
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
else:
    STATIC_ROOT = %REAL_PATH_TO_PRODUCTION_STATIC_FOLDER%
    MEDIA_ROOT = %REAL_PATH_TO_PRODUCTION_MEDIA_FOLDER%

Into urls.py you must add:

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings

from news.views import Index

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    ...
    )

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

In Django 1.8 you can set template paths, backend and other parameters for templates in one dictionary (settings.py):

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            path.join(BASE_DIR, 'templates')
        ],
        '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',
            ],
        },
    },
]

Official docs.

Stefano Munarini
  • 2,711
  • 2
  • 22
  • 26
Dunaevsky Maxim
  • 3,062
  • 4
  • 21
  • 26
6

I also had issues with this part of the tutorial (used tutorial for version 1.7).

My mistake was that I only edited the 'Django administration' string, and did not pay enough attention to the manual.

This is the line from django/contrib/admin/templates/admin/base_site.html:

<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>

But after some time and frustration it became clear that there was the 'site_header or default:_' statement, which should be removed. So after removing the statement (like the example in the manual everything worked like expected).

Example manual:

<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
jpoppe
  • 2,228
  • 24
  • 25
5

In django 3.1, go to setting of your project and import os

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        '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',
            ],
        },
    },
]
Prabesh
  • 51
  • 1
  • 2
4

Alright Let's say you have a brand new project, if so you would go to settings.py file and search for TEMPLATES once you found it you just paste this line os.path.join(BASE_DIR, 'template') in 'DIRS' At the end, you should get somethings like this :

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'template')
        ],
        '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',
            ],
        },
    },
]

If you want to know where your BASE_DIR directory is located type these 3 simple commands:

python3 manage.py shell

Once you're in the shell :

>>> from django.conf import settings
>>> settings.BASE_DIR

PS: If you named your template folder with another name, you would change it here too.

3

Contrary to some answers posted in this thread, adding 'DIRS': ['templates'] has no effect - it's redundant - since templates is the default path where Django looks for templates.

If you are attempting to reference an app's template, ensure that your app is in the list of INSTALLED_APPS in the main project settings.py.

INSTALLED_APPS': [
   # ...
   'my_app',
]

Quoting Django's Templates documentation:

class DjangoTemplates¶

Set BACKEND to 'django.template.backends.django.DjangoTemplates' to configure a Django template engine.

When APP_DIRS is True, DjangoTemplates engines look for templates in the templates subdirectory of installed applications. This generic name was kept for backwards-compatibility.

When you create an application for your project, there's no templates directory inside the application directory. Django admin doesn't create the directory for you by default.

Below's another paragraph from Django Tutorial documentation, which is even clearer:

Your project’s TEMPLATES setting describes how Django will load and render templates. The default settings file configures a DjangoTemplates backend whose APP_DIRS option is set to True. By convention DjangoTemplates looks for a “templates” subdirectory in each of the INSTALLED_APPS.

Peter Chaula
  • 3,456
  • 2
  • 28
  • 32
  • 1
    Well said. Worth to mention the Templates documentation and what it says regarding the `templates` directory. – ivanleoncz Dec 12 '20 at 23:54
2

By default django looks for the template folder in apps. But if you want to use template folder from root of project, please create a template folder on root of project and do the followings in settings.py:

import os

TEMPLATE_DIR = os.path.join(BASE_DIR, "templates")
TEMPLATES = [
   {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [TEMPLATE_DIR],
    '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',
            ],
        },
    },
]
1

In django 2.2 this is explained here

https://docs.djangoproject.com/en/2.2/howto/overriding-templates/

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

INSTALLED_APPS = [
    ...,
    'blog',
    ...,
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        ...
    },
]
soda
  • 443
  • 6
  • 19
1

basically BASE_DIR is your django project directory, same dir where manage.py is.

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            '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',
                ],
            },
        },
    ]

DanielM
  • 3,598
  • 5
  • 37
  • 53
dave
  • 13
  • 3
1

This is for DJANGO version 4.x.x

To add templates folder open file settings.py and modify 'DIRS': [BASE_DIR / 'templates'],

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        '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',
            ],
        },
    },
]
andyuxui
  • 11
  • 1
0

You can easily add template folder in settings.py folder, os.path is deprecated in django 3.1, so you can use path instead of os.path. You just have to import path in settings.py, you have to specify the base directory, then you have to specify template path, and last but not the least, you have to add template folder path in TEMPLATES = [{}], for example:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

TEMPLATE_DIR = Path(BASE_DIR, 'templates') (you can name TEMPLATE_DIR to any name)

TEMPLATES = [
{

    'BACKEND': 'django.template.backends.django.DjangoTemplates',

    'DIRS': [TEMPLATE_DIR],

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

        ],
    },
},

]

0

One interesting thing I noted for templates searching

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        #'DIRS': [os.path.join(BASE_DIR,"templates")],
        'DIRS': [],
        'APP_DIRS': True,

if the app folder have templates sub-folder then only it is searched and listed under Template-loader postmortem

If app/templates do not exist, it is not listed in error messages. Understanding this will prevent newbee to add template folders via DIRS directive