Guide on Django Templates and How to fix TemplateDoesNotExist error

Share your love

I know, it is annoying- writing your first HTML file in Django and you get the TemplateDoesNotExist error right into your face when you try accessing the intended webpage.

Well, you shouldn’t worry because a couple of lines of code or changes in your directory structure will fix the error, and you can go back to creating the next amazing web app, mate.

To fix the TemplateDoesNotExist error in Django, you need to ensure you have checked the following things:

  1. Configured Django to look at directories in that you’re keeping your template files (.html files). Thus, project-level and app-level template directories must exist, and Django must be configured to look into such folders using APP_DIRS and DIRS configuration settings.
  2. Ensure that you are referencing an existing templates file.
  3. Ensure the .html file referenced in your view is in the correct file system location.
  4. Ensure you have an existing project-level templates directory. Besides, you have configured Django to look for .html files within this directory by specifying the directory location as the value for the TEMPLATES dictionary key, DIRS.
  5. Ensure you have set Django to look for the app-level templates directory by setting the TEMPLATES dictionary key, APP_DIRS, to True. Besides, create the templates directory for each app using app-level templates.
  6. No typos in your .html files and your templates names used in each view.

If you’re not familiar with Django’s template directory structure best practices, you should read on to familiarize yourself with the app-level and project-level templates directories.

Django looks for templates within two folders within your project root/base directory (the directory containing your manage.py file),

  1. A project-level templates directory and
  2. The app-level directory.

The project-level directory resides within the Django project root directory, where your manage.py file resides. The directory is commonly named as ‘templates‘.

On the other hand, the app-level templates directory resides within the directory of your Django app. For example, if you have a Django app called blog, the app-level templates directory for the blog app will be /blog/templates.

To use project-level and app-level templates in your Django project, there are a couple of things your need to do. Let’s see in detail how to configure Django to look for .html files within these directories.

How to configure app-level templates directory in Django

When using the app-level templates directory, you store all the .html files used in the views of that specific Django app. By default, Django comes preconfigured to use an app-level templates directory.

In the Django project configuration, you instruct the Django templates loader to look for app-level .html files using the following line in your setttings.py file.

        "APP_DIRS": True,

The APP_DIRS dictionary key resides within the TEMPLATES dictionary in your Django project’s main configuration file, settings.py.

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        # specify the project-level directory here
        "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",
            ],
        },
    },
]

Thus, to locate the setting that instructs the Django template loader to look for templates inside each app, you must look for the TEMPLATES dictionary, and within it, you will find the APP_DIRS key.

Configure Django to use app-level templates

The key takes a boolean value of True or False.

By default, the value is set to True, instructing the Django template loader to look for .html files within the app templates directory.

When set to False, the Django template will avoid looking for .html files within the templates directory of each app.

Setting the value of APP_DIRS to False is a common cause of the TemplateDoesNotExist error in Django when using app-level templates.

Thus, when you face the TemplateDoesNotExist error in Django, a common thing to do is to look at whether you have set the value of the APP_DIRS key to False.

To use app-level templates in a Django app, you need to create a new directory called templates inside the app’s directory. Suppose you have an app called blog; you need to create the templates directory inside the blog directory. Thus, /blog/templates.

How to create app-level templates directory in Django

Inside the templates directory, create your .html files.

To reference these .html files in your views, you just need to enter their name without using the directory. So, if you have list.html in your /blog/templates directory, you just need to use list.html in your view.

def student(request, id):
    student = get_object_or_404(Student, id=id)
    context = {
        'student': student
    }
    return render(request, template_name='index.html', context=context)

NOTE: I have not referenced by list.html file as templates/list.html in my view

def student(request, id):
    student = get_object_or_404(Student, id=id)
    context = {
        'student': student
    }
    return render(request, template_name='templates/index.html', context=context)

If you do this, you will definitely get the TemplateDoesNotExist error in Django

However, that does not mean that you cannot create subdirectories in your app-level templates directory.

You can!

You just need to reference the directory in your views. So, if you have a new done.html file inside the /blog/templates/create/ directory, you need to include the ‘create‘ directory when referencing the file in your views.

def student(request, id):
    student = get_object_or_404(Student, id=id)
    context = {
        'student': student
    }
    return render(request, template_name='create/index.html', context=context)

Why you may need to use app-level templates in Django

  1. You may need to use app-level templates if you intend your Django app to be pluggable and reusable. When you intend to reuse your Django app for other projects or share it with other developers, you should keep all the .html files of that app in its app-level templates directory. Thus, you or other developers can download the app with its templates and use them in their projects.
  2. If your Django project will scale to a very large project, keeping each app with its related resources is good practice. Thus, all the .html files should exist in the app-level templates directory of each app. Therefore, you avoid cluttering the main project-level templates directory with too many .html files and enhance modularity.

How to configure project-level templates directory in Django

Alternatively, you may prefer to keep all your .html files within a common directory for all your apps. If that’s so, then you must use the project-level templates directory, which is a directory used to store all the templates files for your Django project and templates that are reusable, e.g. base.html.

For project-level templates directories, you create a single templates directory inside the root directory of your project, place all your .html files in that directory, and reference them across the views in your Django apps.

First, you need to create a new directory inside the root directory of your Django project. This is the folder containing the manage.py file.

After creating the project-level directory, you will need to instruct Django to look for templates files within this new directory. You do that by using the DIRS dictionary key of the TEMPLATES dictionary in your settings.py file.

How to configure Django to use project-level templates

After creating the directory, you may place all the .html files inside the directory for all your Django apps.

Where to create templates files in Django

However, as your project scales, you will have an issue referencing them because:

  1. You will have too many files in one directory
  2. Some .html files will have similar names leading to a conflicting naming system or the addition of unnecessary characters in your file names.

An alternative to storing your .html files is to create new directories using the names of the apps inside the project-level templates directory. Thus, each app will have its directory in the project-level templates directory. You store all the .html files within each directory associated with the app.

For example, if you have blog and book apps in your Django projects, you will have to create two new directories inside the project-level templates directory: /templates/blog/ and templates/book.

For templates files used in your blog app, you store them inside the /templates/blog/ directory.

The same is true for the book app and other apps in your Django project.

When referencing these templates files residing within your project-level templates subdirectories, you need to include the directory name in your views. So, if you have /templates/book/all_books.html, you must include /book/ in your views:

class BooksListView(ListView):
    model = Book
    template_name = 'book/list.html'
    

Why you may need to use project-level templates in Django

  1. When you want to use a reusable templates .html file across your Django website. Examples of .html files you may need to use to achieve consistent layouts include base.html, nav.html, and footer.html files.
  2. To inherit the power of Django authentication functionality, you will need to create a project-level templates directory for your project. Thus, you will use the project-level templates directory to store login.html, signup.html, password_reset_done.html, and password_reset_confirm.html files.

Related Questions

What is APP_DIRS in Django?

APP_DIRS instructs Django’s template loader to look for .html files inside the app’s directories. Thus, each app should have the templates directory and the templates in it for Django to iterate them and match them to the appropriate view. Besides, you must set this dictionary key, APP_DIRS value, to True for Django to look for templates inside each app’s ‘templates’ directory.

Thus, APP_DIRS enables you to instruct Django’s templates loader to look for templates or .html files inside the app’s directories.

In summary, to use app-level templates in Django, you must

  1. Set the APP_DIRS dictionary key value to True
  2. Create a templates directory in each app using app-level templates
  3. Create your templates files (.html files) inside the app/templates/ directory

What is BASE_DIR in Django?

BASE_DIR is a configuration settings variable used in Django to store the value of the current project root directory. Thus, it holds the value of the directory containing the manage.py file and the project’s main directory, which is the directory hosting the Django configuration settings file, setttings.py; project-level URL configuration file, urls.py; wsgi.py; and asgi.py file.

When you decide to use the project-level templates directory, you may use the BASE_DIR variable to reference the root directory, which contains the templates folder. Thus, setting the dictionary key, DIRS = BASE_DIR / ‘templates’ indicates that: in the current Django project directory, locate the ‘templates’ folder and use it as one of the project-level templates directories.

Thus, Django will iterate through this directory to locate any .html file matching the URL requested by a user.

Share your love
Badi
Badi

Badi here, creator of ngangasn.com— A website dedicated to providing helpful information and how-to's of web development and hosting. Inspired by a fascination to write the most efficient code to make a computer laugh, & humans, Steve has a passion for organizing characters to create code and informative content.
What makes me happy?
Well, nothing like the feeling of finally figuring out that one pesky bug that's been driving me crazy.

Leave a Reply

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