Inheritance in Jinja
00:00 In the previous lesson, I showed you how to use Jinja2 with Flask. In this lesson, you’ll learn how to compose templates together, allowing you to better manage your HTML.
00:12 HTML is like a rambling uncle taking forever to say very little. The pages themselves are bad enough, but websites tend to make this worse. Most sites have a significant amount of content that shows up on every single page. Think nav bars, footers, and even the base structure and style of the page. Templates provide a way of managing this complexity, allowing you to create snippets of HTML and compose them together.
00:41 This allows you to create a base page that defines the look and feel of the site, while the child page implements the actual content. This has the added bonus that if you want to make a change, you can do it in one place, and it flows across the entire site.
00:58 There are two ways of doing this kind of composition: a class-like inheritance mechanism and import-style inclusion. Let’s take a look at both of these.
01:10
Another lesson, another view in the Flask app.py
file. This one is called projects
and is similar to what you’ve seen before: a context dictionary and a call to .render_template()
.
01:23 Let’s look at the associated HTML.
01:29
Okay, surprise. This isn’t projects.html
, but something else called nav.html
. This short template renders a nav bar. The first part here loops through a list containing the names of views, and the second part uses a function that’s built into flask called url_for()
.
01:51 This takes a string representation of a view, its name, and outputs the corresponding URL. Essentially, this block is looping over some of the view names and outputting an HTML link tag for each.
02:05 Let see how to use this nav sub-template inside of another template.
02:13
Still not projects.html
. This is nav_base.html
. This template uses the {% extends %}
tag, which means it inherits from another template.
02:24 This works somewhat like class definitions, where this template will include everything from the parent, but with the ability to override certain blocks.
02:34 You may recall I did some hand-waving back in the previous lesson when I spoke about the block tags. Blocks are a way of naming a chunk of texts, and with inheritance, you can override the block in a child template.
02:47
If you were to render nav_base
, you would get everything from base.html
, except in base where it says {% block content %}
, the result in here would be used instead.
02:59
Of course, you might want to use what is in the parent, so the parent’s block is made available through the built-in super()
function. With this line here, the content block will contain everything in the parent’s content block and then everything else in this content block. By doing it this way, you can decide whether or not to include the parent’s stuff when you define an override.
03:23
The {% include %}
tag gets replaced with the template named inside of it, so if I were to render nav_base
, it would have the HTML code from base.html
, with the stuff in the content block replaced with this content block, which itself defines a <header>
tag and inserts the content from nav.html
.
03:45 So you’ve got two different choices when you want to compose pieces together. Inheritance is good for defining a base page like the look and feel of your site, and then you override blocks in a child to graft new content inside.
03:59
This is similar to a child inheriting from a parent class in Python code. Alternatively, you can suck templates into a template using the {% include %}
tag, which is more like a function than a class.
04:12
This is useful for encapsulating longer pieces of HTML in their own files or for defining chunks of HTML that you want to reuse but might not show up everywhere. You may recall that the project’s view—yeah, I know that was like, so five minutes ago—used a template called projects.html
. Well, it’s time to take a look at that one.
04:37
And here it is. It extends nav_base
, meaning it’s the grandchild of base
, so you get the content from both.
04:48
It also declares a block named content, and so like its parent, it uses super()
to include the parent’s version of the block, and because the parent uses super()
, you’ll get the grandparent’s copy of the block as well.
05:00
The rest of this template is the actual content I want on the project’s page. It’s a for
loop that creates an unordered list of Jenny’s projects.
05:10 Let’s go check this out in the browser.
05:22
Nothing earth-shattering here, but stop and think for a second about where all this came from. The structure of the page, including this title, is from base.html
.
05:33
This nav bar is from nav.html
, which got included in nav_base.html
, and then the projects themselves were included in the actual projects.html
file.
05:45 This pattern might feel a little bit like overkill, but it’s one I use in my web development all the time. Quite often you’ll have landing pages on your site that don’t have a nav, or pages for logged-in users, and then for the general public.
05:59
By separating base
and nav_base
, you can appropriately deal with these situations, having the nav on or off as you need simply by inheriting from the right file. Alternatively, you could do this with a context variable.
06:12
You could put a conditional in base.html
that checked for nav=True
and include the nav sub-template only if that is the case. Whichever you’re more comfortable with works fine.
06:26 Tags aren’t the only way you can alter the appearance of a page. You can also use filters to modify values before they are rendered. I’ll show you how in the next lesson.
Become a Member to join the conversation.