Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Create a Template

In this lesson, you’re going to create a template for your Django app so you won’t have to paste all your HTML directly into your views. Django has already provided you with the import statement you’re going to need for this:

from django.shortcuts import render

Now that you have render(), use it in your function with the template name 'projects/index.html':

# Create your views here.
def project_list(request):
    return render(request, 'projects/index.html')

Comments & Discussion

Gascowin on Oct. 19, 2019

May i ask; why is it that in you have

def project_list(request):
    return render(request,'projects/index.html') 

instead of

def project_list(request):
    return render(request,'templates/projects/index.html') 

? My understanding here is that we are passing in the path to the file index.html and since and the templates folder are in the same directory we would need the path ‘templates/projects/…’ instead of ‘projects/…’ Thanks in advance.

Martin Breuss RP Team on Oct. 19, 2019

Great question! You are completely right in that we are pointing Django to the location of the index.html file.

The reason we don’t need to spell out templates, is that Django by default searches for your HTML files in a templates folder, where it aggregates all the templates from your whole project.

I talk about it some more in the video about Django’s Double-Folder Structure, but essentially the reason is that templates is defined as Django’s default location for templates and therefore doesn’t have to be explicitly mentioned.

reblark on Oct. 30, 2019

I have checked my code and tried this several times but consistently get the error that “projects/index.html” does not exist. But it does and it is in the templates/projects folder. I thought at first it was like your experience in the video that the file had not been registered, but surely it’s registered after all these attempts. Here is the template-loader-postmortem: Django tried loading these templates, in this order:

Using engine django:
django.template.loaders.filesystem.Loader: /Users/reb/Django/Django-CA/projects/templates/projects.index.html (Source does not exist)
django.template.loaders.app_directories.Loader: /Users/reb/Django/Django-CA/rbvenv/lib/python3.7/site-packages/django/contrib/admin/templates/projects.index.html (Source does not exist)
django.template.loaders.app_directories.Loader: /Users/reb/Django/Django-CA/rbvenv/lib/python3.7/site-packages/django/contrib/auth/templates/projects.index.html (Source does not exist)
django.template.loaders.app_directories.Loader: /Users/reb/Django/Django-CA/projects/templates/projects.index.html (Source does not exist)

The file is there!

Dan Bader RP Team on Oct. 30, 2019

@reblark Looks like you might have a typo in the code somewhere where you’re referencing that index.html file:


Instead of projects/index.html it says projects.index.html (. instead of /).

reblark on Oct. 31, 2019

Hi Martin, Again, thanks for the response and suggestions but I need to tell you a little story. I looked at my code many, many times this morning and thought it was right. I could not find a mistake. So, I took a break and on the break, I tripped and busted my knee cap. I spent the next several hours in the ER. I came back discouraged, but after resting awhile, started this video over again. In the very first code presentation, views, I found the mistake. I couldn’t believe it. I made a simple change and ‘voila,’ it worked. I don’t know what to make of this. Maybe I just don’t have what it takes to be a programmer. I make too many mistakes and too many times I just can’t see those mistakes no matter how hard I look. However, if I continue, I believe that programming well will teach me something and improve my discipline. Thanks again for your graciousness.

Martin Breuss RP Team on Oct. 31, 2019

Don’t give up! Everyone runs into these situations where you just can’t find the error. Taking a break and coming back to it in a bit is often the best way to tackle it. I’d suggest to avoid trips to the ER, though if possible–there are definitely more fun ways to take a break!

Glad you figured out your error, and most importantly I hope everything’s alright with your knee!

Keep up the work if you find it interesting. Learning to program can definitely be a great asset in many ways. :)

reblark on Nov. 1, 2019

I don’t believe this. The response from Dan Bader was exactly right. It took me a day to find it, but I did find. I just saw Dan’s response for the first time and I am so impressed that someone actually answered my question. I think in my long missive whining about MOOCs I mentioned a company in Florida that was bought by Pluralsight who had a guy who as absolutely great at answering questions. I’ll be doing more courses with Real Python. I might learn something.

eclaudio on Dec. 2, 2019

I just attempted to push this group of files up to GitHub and had over 4518 files that are about to push. Is this correct? And if not, what did I do wrong?

Martin Breuss RP Team on Dec. 3, 2019

Hello @eclaudio. You probably committed your whole Virtual Environment to GitHub. To avoid pushing all these files, you should add your .env to your .gitignore file.

eclaudio on Dec. 3, 2019

@MartinBreuss 1. Thank you 2. the detail is great.

If we are using the above project as the file structure, where is the best place to create my .gitignore file?

eclaudio on Dec. 3, 2019

You Guys ROCK!!!

Martin Breuss RP Team on Dec. 3, 2019

.gitignore should be always right in the base folder where you initiated your repo with git init.

And thanks! You rock 🚀! :))

eclaudio on Dec. 4, 2019

@MartinBreuss yup it worked thank you!!

Martin Breuss RP Team on Dec. 7, 2019

Great that it worked! I’d suggest to keep the .gitignore file one level higher, in your django-portfolio folder. That should be the root folder of your project. However, it looks like it’s now on the same level as your file?

josemariapolanco on Dec. 25, 2019

Why can’t we specify projects.templates inside of TEMPLATES in It looks a lot cleaner than what’s suggested in the video.

Martin Breuss RP Team on Dec. 29, 2019

You can specify what templates Django looks into in in the TEMPLATES list in the DIRS list. Here’s more to read about it in the official docs. Generally, there’s a lot you can customize when using Django, and that includes how to handle templates. If it feels cleaner to do it differently, do give it a go. :)

Rodrigo Vieira on Jan. 21, 2020

I could fix the “Template Not Found” error by just rerunning the ./ runserver command, without registering the templates directory in the TEMPLATES list in the file.

Brandy Wright on March 3, 2020

The tutorials and state of the files on screen video dont match. I believe it is because on one of the first tutorials in this course, I saw the .zip of the project.

So some stuff already works for me and I’m not getting the errors (errors are the point of this chapter).

The strange thing is parts that work when the file or text is NOT present.

For example: templates was already registered but the ‘DIRS’: was just []. The template still loads fine.

I added to it [os.path.join(BASE_DIR, 'projects/templates')], its still working. I’m curious about this…

Martin Breuss RP Team on March 5, 2020

Hi @Brandy Wright. The .zip file of the project already contains the finished code. To get the full experience of actively running into all the errors we’re covering here, I’d suggest to avoid that file and build the project from scratch. Just follow this tutorial step-by-step and you should be fine :)

Template DIRS

As for what you noticed with the DIRS list being empty in Django automatically registers template directories in registered apps, when they are called exactly that: templates. So there is no need to add these folder paths to You can define different directories as template directories, but then you will need to add them to the DIRS list.

I personally think it makes sense to be explicit and even record the template dirs of your apps in here.

Tomas Menito on March 9, 2020

Hi, great tutorial!

I have one quick question that is, instead of:

os.path.join(BASE_DIR, 'projects/templates')

Would it be better to use:

os.path.join(BASE_DIR, 'projects', 'templates')

To be more generic about os paths?


Martin Breuss RP Team on March 9, 2020

Hi @Thomas Menito and thanks for your comment! Yes, you’re absolutely right. With os.path.join it would be better to use:

os.path.join(BASE_DIR, 'projects', 'templates')

That makes it more general and avoids hard-coding the path separator, which might be different on different operating systems. Thanks for your 🦅👁 and for commenting here! 🙌

Andrew on May 26, 2020

Hello, In os.path.join(BASE_DIR, ‘projects/templates’) why don’t you have ‘projects/templatets/projects’) ? How does django know that it needs to go inside the second folder projects to get to the file index?

Martin Breuss RP Team on May 28, 2020

Hi @Andrew - great question :)

If you look a bit closer in the TEMPLATES settings dictionary right there in, you will find another option called APP_DIRS that is by default set to True:

        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        # more stuff

This setting ensures that Django automatically considers all files that are located inside of a folder called templates/ inside of each of your apps that you have registered in your project. You can experiment with setting it to False and notice how the templates are not found anymore.

Become a Member to join the conversation.