Template Basics

00:00 In the previous lesson, I gave an overview of the course. In this lesson, I’ll show you how to write a Jinja2 template. Jinja2 is a text-based templating system. Through it, you can populate and render a template using variable replacement; tags, including conditionals, looping, inheritance and inclusion, and function-like macros; and you can also modify variable data on the fly using filters.

00:30 Jinja2 is a third-party library and, as such, is installed using pip. As always, best practice here is to use a virtual environment. Note that the reason I keep saying Jinja2 rather than just Jinja is there is a Jinja, but it’s legacy.

00:47 If you attempt to pip install Jinja without the 2, you’ll get an error in Python 3. Trust me, I found that out the hard way.

00:55 Once you’ve got it installed, head into the REPL to create your first template. First off, you need to import the library. Don’t forget the 2. Everything in Jinja is done through an environment.

01:14 Later, this object is used to configure how templates are sourced, but for now, the default is fine.

01:26 The .from_string() method on the environment creates a template object from a string logically enough. The double braces here indicate a variable substitution. When rendered, the template’s context contains a dictionary with key-value pairs.

01:42 Any key named in double braces ({{}}) is replaced by its corresponding value. The double braces are sometimes known as mustache braces. Now that you have a template, you render it using the .render() method, passing in any context variables that can be used to turn the template into a result. And there you go, that’s your first template.

02:05 The value of "name" has been replaced with "World", and the most famous string in programming is your result.

02:16 As you’ve seen, templates are based on strings, but a far more common way of getting a template is to load them from a file rather than hard-coding them in your program.

02:26 This is where that environment thing comes in. When you construct an environment, you can tell it to load templates from a directory. Let’s go into the REPL and play with this.

02:38 Suppose you were teaching a course on Python, and you wanted to send a customized message to the students who did well on a recent test. Templates allow you to do this, using a concept similar to a mail merge in word processing tools. This program loads a template, loops through the student data and outputs a result file for each student containing the message to be sent. If you were doing this for real, you might also have it email the message, but I’ll skip that.

03:07 This chunk near the top is the data that is to be used in the template. It includes the name of the test, the max score, and a list of dictionaries with the results for the top students.

03:19 Here, like in the example before, I’m creating an environment. This time, though, I’m passing in the FileSystemLoader. This loader takes the name of a directory as configuration, and all future template loads will be based on files in that directory. With the environment set up, next it’s time to load a template. Mine is called good.txt.

03:41 I’ll show you the contents of that in just a minute. With the template in place, it is now time to render it for each student. First off, I create a filename for the output. Next, I do the actual rendering. Notice what I’m passing in here.

04:00 It’s the dictionary for the specific student that I’m creating a message for, as well as the max score and test name. This forms the context for the template, and when the template is rendered, the values corresponding here can be used inside of it.

04:16 Now that I’ve called .render() and put it in content, all that is left is to write the result to a file. So here I open a file, and there I write the content.

04:27 At the end, just so that you know what’s going on, I print out a message to the screen saying that I’ve done this. Now let’s take a look at good.txt, the template that gets used by this program.

04:42 At the top of the file here, you see {# #} or hash or pound—whatever you want to call that symbol. That’s the template engine’s comment character, so this first line is just a comment telling you what the file is.

04:57 The next line is the greeting. It uses the mustache braces you saw in the previous example to write the student’s name. Remember when .render() was called?

05:06 That method took the student dictionary and some keyword arguments for the max score and test name. .render() wants key-value pairs for everything and treats the dictionary as a grouping of them. So there’s no student object, just the key-value pairs from inside the students dictionary injected directly into the context.

05:27 This next line has the test name, and this one has the score from the student dictionary and the max_score value that was passed in as a keyword argument.

05:37 All right, back to the code.

05:42 And now I’ll run it all on the command line.

05:49 And there are the three messages having been created. Let’s look at one of the files.

05:58 This is the message for Willow, and you can see how her name and her score, along with the max score and test name, have been replaced inside of the resulting file.

06:12 You can do more than just variable substitution. You can manage the flow of content in a template with tags, and that’s what’s in the next lesson.

Become a Member to join the conversation.