Template Loader finds the template but template is not loaded
TemplateDoesNotExist at /cardpayment/
cardpayment.html
Request Method: G
Find settings.py in your python project and add following line. I hope it will work
SETTINGS_PATH = os.path.normpath(os.path.dirname(__file__))
TEMPLATE_DIRS = (
os.path.join(SETTINGS_PATH, 'templates'),
)
I'm also using the DIRS
config option in a similar way to you and I've just run into the same problem in Django 1.8.2. The issue seems to relate to the way you invoke django.shortcuts.render
(or django.shortcuts.render_to_response
) in your views - are you using these?
TL;DR - try changing your invocation of render_to_response
in your views so that you don't pass a context_instance
or any deprecated argument, such as the previously often used django.template.RequestContext
. If you do pass a context_instance
, or any deprecated argument, the django template loading code uses a legacy path that doesn't support the DIRS
option and your template will not be loaded - even if it exists on disk.
Here's a section of relevant code from the Django source (django/shortcuts.py
) that shows how this situation comes about:
def render_to_response(template_name, context=None,
context_instance=_context_instance_undefined,
content_type=None, status=None, dirs=_dirs_undefined,
dictionary=_dictionary_undefined, using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
if (context_instance is _context_instance_undefined
and dirs is _dirs_undefined
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
content = loader.render_to_string(template_name, context, using=using)
else:
# Some deprecated arguments were passed - use the legacy code path
content = loader.render_to_string(
template_name, context, context_instance, dirs, dictionary,
using=using)
return HttpResponse(content, content_type, status)
If you follow this through to the loader's render_to_string
method (in django/template/loader.py
) you can see your template won't be loaded if you pass any deprecated arguments to render_to_reponse
in your views:
def render_to_string(template_name, context=None,
context_instance=_context_instance_undefined,
dirs=_dirs_undefined,
dictionary=_dictionary_undefined,
request=None, using=None):
"""
Loads a template and renders it with a context. Returns a string.
template_name may be a string or a list of strings.
"""
if (context_instance is _context_instance_undefined
and dirs is _dirs_undefined
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
if isinstance(template_name, (list, tuple)):
template = select_template(template_name, using=using)
else:
template = get_template(template_name, using=using)
return template.render(context, request)
else:
# Some deprecated arguments were passed - use the legacy code path
for engine in _engine_list(using):
try:
# This is required for deprecating properly arguments specific
# to Django templates. Remove Engine.render_to_string() at the
# same time as this code path in Django 2.0.
if isinstance(engine, DjangoTemplates):
if request is not None:
raise ValueError(
"render_to_string doesn't support the request argument "
"when some deprecated arguments are passed.")
continue
# Hack -- use the internal Engine instance of DjangoTemplates.
return engine.engine.render_to_string(
template_name, context, context_instance, dirs, dictionary)
elif context_instance is not _context_instance_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the context_instance argument." %
engine.name, stacklevel=2)
elif dirs is not _dirs_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the dirs argument." % engine.name,
stacklevel=2)
elif dictionary is not _dictionary_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the dictionary argument." %
engine.name, stacklevel=2)
except TemplateDoesNotExist:
continue
if template_name:
if isinstance(template_name, (list, tuple)):
template_name = ', '.join(template_name)
raise TemplateDoesNotExist(template_name)
else:
raise TemplateDoesNotExist("No template names provided")
i've been running into the same problem, the solution that work was to specify my template directory (projects/templates) in templates settings like this:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['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',
"django.core.context_processors.media",
],
},
},
]
Django’s template system was overhauled in Django 1.8 when it gained support for multiple template engines.
The TEMPLATES settings
A new setting was introduced in Django 1.8: TEMPLATES
. All existing template-related settings were deprecated.
During the deprecation period, Django will create a backwards-compatible TEMPLATES
based on the TEMPLATE_*
settings if you don’t define it yourself.
Here’s how to define TEMPLATES
in your settings module.
If you’re using the default value of TEMPLATE_LOADERS
, that is, if it isn’t defined in your settings file or if it’s set to:
['django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader']
then you should define TEMPLATES as follows:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
# insert your TEMPLATE_DIRS here
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]
More information can be found here https://docs.djangoproject.com/en/1.11/ref/templates/upgrading/
TemplateDoesNotExist... cardpayment.html
might mean Django can't find cardpayment.html
, or it might mean it can find cardpayment.html no problem, but can't find some {% include 'cardpayment_subsection.html' %}
within it.
Explanation:
I got this error just now, in a project that's been working for years, and the other solutions here didn't help me.
My cardpayment.html
was being found by the template loaders, but contained some nonsense which meant it could not be rendered.
The error messages mislead me into thinking Django didn't know the file exists, when in fact it knew it existed, just couldn't successfully render it.
For a while everything was working fine: cardpayment.html
was being rendered without a problem.
views.py
def cardpaymentview(request):
return render_to_response("cardpayment.html", {
"message": "Hi SO"
}, context_instance=RequestContext(request))
Suddenly, even though I hadn't been editing cardpayment.html
, I got that error:
TemplateDoesNotExist at /cardpaymentpage: cardpayment.html
Using loader django.template.loaders.app_directories.Loader:
folder/lib/python2.7/site-packages/django/contrib/admin/templates/cardpayment.html (File does not exist)
folder/project/app1/templates/cardpayment.html (File does not exist)
folder/project/app2/templates/cardpayment.html (File does not exist)
folder/project/paymentapp/templates/cardpayment.html (File exists)
The problem was that my cardpayment.html
in turn has an include
calling another template:
{% include 'cardpayment_subsection.html' %}
I created the error by renaming the file cardpayment_subsection.html
to something_else.html
, without editing cardpayment.html
, so that include
command naturally failed.
But as you can see, the debug message didn't indicate the problem was callling the cardpayment_subsection.html
(file no longer exists).
Summary: if other solutions don't work for you, try creating a test file cardpayment2.html
that simply says "Hello world" and see if you can at least render that instead. Maybe the cardpayment.html
file is being read, but has an error within it. (In my case, I needed to change the {% include '____.html' %}
to refer to a file that actually does exist!)
I had the same problem and it was solved after changing the order of the apps in INSTALLED_APPS
in the settings.py file.
Put your app's name first on the list:
INSTALLED_APPS = [
'module_name',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]