Template Inheritance
In this lesson, you’ll learn about template inheritance as well as a common software development principle: DRY (Don’t Repeat Yourself). Django’s template inheritance allows you to write a particular bit of code only once in one place and then inherit from there to the other places where you want to use it.
00:00
Welcome to this video about template inheritance. Here, I want to sneak in a little information about a common software development principle. It’s called DRY: don’t repeat yourself. Let’s take a look at how this applies in our templates. So, back here in all_projects.html
, where we just fixed up our button, there’s all this HTML structure up here: a <!DOCTYPE>
declaration with HTML tags, we have the <head>
, and remember, we had to copy this link to the Bootstrap CDN from our index.html
page that we’re not using anymore.
00:37 So there’s some leftover code, but maybe we kept it around because we thought this could be useful. It’s all, like, lots of excuses for things that you actually don’t want to do.
00:47
So I’ll go ahead and clean this up a bit. The first thing I want to do is get rid of index.html
. We don’t need this, we’re not linking here anymore, so let’s just delete it for now.
01:01
Okay. Next, we want to not have to repeat ourselves, so, “Do not repeat yourself.” We want to see—like, inside of detail
, I have this <!DOCTYPE>
declaration and everything again.
01:13 I would have to drop in the Bootstrap CDN again. This is all stuff that we don’t want to do twice, because it’s exactly the same, okay? Django has something that’s called template inheritance that allows us to only do this once and in one place, and then inherit from there to the other places where we’re using it.
01:33 To build this in the correct way, let’s first take a look at a couple of slides and walk over it, and then we’ll come back to the code to actually build it out.
01:42
To avoid repeating ourselves, we’re going to look at two files. First one is going to be base.html
. Inside of base.html
is where we’re going to put all the basic HTML code and something like a <footer>
, or a <header>
—something that’s going to repeat all over in every page for my whole website.
02:01
So, inside of base.html
—and imagine that on top here, is going to be the <!DOCTYPE>
declaration, we’re going to have our <head>
, it’s going to be the same everywhere—the <title>
, et cetera, and then, yeah, let’s assume down here is a <footer>
, for example.
02:14
Somewhere in there, I’m putting this {% block content %}
. It’s a template tag that’s just called a block
tag, I guess. It consists of two parts: the one that opens it and the one that closes it.
02:27 I want you to imagine it just like that, that there’s this space that we’re opening up by creating this block, and this space is ready to take some changing HTML content.
02:38
But we’re not going to be putting this inside of base.html
, this is just where it’s eventually going to go. So, everything around it stays the same, and this one is going to get exchanged with whatever we’re going to put inside of {% block content %}
in our second file. So, let’s take a look at the second file.
02:55
This one can be whatever template you’re going to be mixing together with base.html
, so this can be multiple ones. For us in our project, it’s going to be all_projects
as well as detail
.
03:08
Both of them are going to inherit from base.html
.
03:12
Inside of this—whatever template it is—there are two things to consider. So the first thing, we need—again—the same block with the same name that we gave it over in base.html
because we need to open up this space again.
03:25
Now, we’re going to be putting something in there, actually. But we need to connect to base.html
by saying, “Okay, this is this block, whatever is in base.html
under this block is going to be replaced with what we’re putting in here.” So, that’s part one, and the second one is at the very top we need to extend base.html
.
03:44
Another Django template tag, and what it simply does is it creates this connection between these two templates. And then finally, if we have all this together, in here between {% block content %}
and {% endblock %}
is where we’re going to write our changing HTML that’s going to be specific for the page that we’re currently looking at.
04:06 Okay, so that was very theoretical. Let’s build this out in practice over in our code.
04:14
The first thing I’m going to do is I’m going to create base.html
.
04:23
PyCharm already gives us the structure, so I’m not going to have to type it out. One thing I will do though, is I’m going to call my page Portfolio
, give it a title, because this is going to be for every page the same, and that’s what I want.
04:40
And then in here, in body
, is where I’m going to open up the block. I’m going to call this block content
. It’s the standard way of calling these blocks in Django.
04:51 You can have multiple different blocks, and then you just need to give them different names but often, this is fine. Often, one of them is enough. Great! So now here, I opened up the space that allows me to later input HTML code that I’m going to write in other templates.
05:10
So if I head back over to all_projects
, now, a lot of these things become obsolete. I can get rid of this, I don’t need it. The <body>
tag, I already have this.
05:23
So, this is going to be interesting. We want to have this in all pages—our Bootstrap link—so I’m taking it out of here, putting it into the head in our base.html
so that we have access to it here, as well as in whichever other template we’re extending this from.
05:44
Back there—oh, so it’s telling me I don’t need those anymore, so let’s get rid of them—there’s only two things missing here now. One is, I need to define the block. I’m going to say {% block content %}
.
05:58
Then remember, in between, we put our HTML of that specific template, and then I’m going to end the block down here. So, that was step one: creating the {% block content %}
and putting our HTML in there. And then step two, you need this other template tag that tells us that we’re extending from base.html
.
06:26 There it is! Now, we’re saving up on all this boilerplate HTML beginning, we don’t need to repeat that Bootstrap CDN, et cetera. And the only HTML that we have in this template is that HTML that’s actually specific for this template. Let’s double-check whether this is still working.
06:46 Reload my page. Everything’s still fine. Awesome. Let’s do the second template!
06:57
Back here in detail
, we have a lot of stuff that repeats again that we can get rid of.
07:20 That’s number one, and number two—extending.
07:37
And with this, we follow the Don’t Repeat Yourself principle and we keep our templates much easier to read, because the only thing that matters here is the code that’s specific to this template and we only keep that code in here and we keep everything else, everything that repeats, inside of base.html
.
07:57
Just double-checking whether everything still works. Perfect! You can also see that Bootstrap style gets applied to this already because now we’re extending the base.html
template that has the Bootstrap CDN included.
08:13 So, it’s going to make it easy for us to nicely style this page, as well, which is exactly what we’re going to do in the next video. See you there!
Martin Breuss RP Team on Oct. 23, 2019
Are you still doing {% load static %}
also in the child templates? I assume you are probably running into this situation.
charneuk on Aug. 13, 2020
I am also getting this error:
TemplateSyntaxError at /projects/1
Invalid block tag on line 12: 'enblock', expected 'endblock'. Did you forget to register or load this tag?
Martin Breuss RP Team on Aug. 14, 2020
Hi @charneuk. Looks like in your case it’s a typo. Double-check your spelling and look at the quoted words in your error message.
Django’s quite a stickler with spelling, but at least it is straightforward about it. :)
charneuk on Aug. 14, 2020
well that worked, ty. HA. damn spelling typos.
gordoncampbell on Dec. 8, 2021
Hi @martin, great videos. Simply explained.
As a fan of working efficiently, I’d love to know what plugin you are using for code completion for the Django Templating Syntax (e.g. when you started typing:
{$ block ...
and the IDE completed it with:
{% endblock %}
Many thanks
Martin Breuss RP Team on Dec. 9, 2021
Hi @gordoncampbell I think I was using the Djaneiro plugin for PyCharm for this course.
You’ll be able to find some plugin for that also if you’re using a different editor. It’s a collection of shortcodes that create common language patterns. Hope that helps! :)
Katya on June 18, 2023
hello! for some reason im getting a blank page after clicking the “read more” in the project page. it worked properly and displayed all the elements before i made the changes shown in the video but it dosent work after. I made sure that the code in html files is correct by compering it to yours. what can be the reason for that?
thank you for your help and guidance! katya
Martin Breuss RP Team on June 20, 2023
@Katya it’s hard to say without seeing your code. If it was working before and stopped working after this change, then there’s probably some small error in how you set up template inheritance.
Does the project page itself still work? If yes, then you could double-check how you set up template inheritance there and find out whether there’s a typo somewhere in the detail.html
page.
If you have your project code up on GitHub somewhere you can share a link and I can take a look.
Become a Member to join the conversation.
Gascowin on Oct. 21, 2019
I accidentally (or shall i say intentionally) included
in base.html since it gets used in the other templates as well but ended up with another one of our “friends”; “TemplateSyntaxError”. The error asks “did you forget to register or load this tag?”
Am I missing something here?…or does this approach not work for ‘static’ files? Thanks.