DEV Community

kaelscion
kaelscion

Posted on • Edited on

The Jinja2 Template: Web Templates for Python

jinja2-web-template

originally published on the Coding Duck blog: www.ccstechme.com/coding-duck-blog

So I was having a conversation with a friend/colleague of mine not too long ago about a project he was working on. He runs a two-person operation that primarily does digital media and marketing. On occasion, he will build a website for somebody to go along with the digital presence he hopes to create for them. He makes no pretenses about his web development skills. "I go to ThemeForest, download a theme, and change the colors, pictures, and text." I really admire that kind of honesty. He has a marketing and business background and knows that most people would rather deal with as few vendors and contractors as possible when starting a business, so he offers Wordpress re-skinning to make himself a one-stop-shop. I usually hear from him when his clients have matured a bit and are looking for something a bit more flexible and dynamic than he can provide. While I understand that a true PHP master can make WordPress do absolutely ludicrous things, PHP just never appealed to me, so I will build with Flask when asked.

One day he asked me how web developers built websites by hand with Flask, Django, Angular, React, Node, etc. "It's not all that different from WordPress actually," I responded, "we just tell the code where to put things and how to make them look rather than a drag and drop interface."

At this, he began to chuckle and shake his head. His reaction is based mostly on what he knows of me. I am the quintessential developer/engineer/code jockey type. The coding aspect to me is the only reason I do it; because I love to solve the puzzle. Sure, I need to pay the bills and, though I technically run my own business, I am far from a businessman. To me, it's the machines. I love to talk to them and listen to them talk back. I have come across many machines that are quite "cheeky", as I refer to them, and rather difficult to work with. This gives them a personality in my eyes; the result of years of neglect or bad configurations to them, are much like negative past life experiences to us: they are shaped by it, molded by it...

Bane

He, on the other hand, is trying to get along and put food on the table plus as much extra as he can. So after a moment, he replies, "Sure, for people like you. But even when I do have to Google something on WordPress and insert code, I know that the top of the page goes into wp-header.php, the bottom goes into wp-footer.php and so on. What you do isn't that easy."

Oh no????

Many people are afraid of programming languages and get into absolute panic mode the moment that they are required to read one. This could be akin to somebody who sees the title of a book on a shelf but in another language. They immediately move on because reading a language you do not understand is intimidating. This leads to misconceptions. Misconceptions that perhaps, some of you have had about how certain front-ends go together. Maybe you think that JS is best with JS and web apps should really only use Node, or React, or the Angular Typescript compiler. But to believe such would be to see Les Miserable on a bookshelf and assume you couldn't read it because you speak English. Yet if you picked it up and opened it, you'd see the title is French because the author is French, and the story was originally written in French, and it takes place in France. But the book itself is translated into English. Now, whether or not Victor Hugo is understandable even if his prose is in your language is another post in itself. But the point is, laying out a Jinja2 app is not all that different from laying our a Wordpress app. The trick: Templates. Now, I don't mean a template that you download from ThemeForest.net that you must first pay for but have little granular control over. I'm talking about a theme for your web app that you build yourself. The best kind of web template is a free web template after all, right? For this, we will not use a repository of pre-made templates, we're going to use build one with an engine. The template engine in question: Jinja2. Let's dispel some myths:

A typical base template looks like this:


<html>
  <head>
    {% if user %}
    <title>Hey there {{ user }}</title>
    {% else %}
    <title>I don't know you!</title>
    {% endif %}
  </head>
  <body>
    <header>
        {% include "header.html" %}
    </header>
    <div class="content">
        {% include "content.html" %}
    </div>
    <footer>
        {% include "footer.html" %}
    </footer>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

So this template lays out a modular HTML document that imports and uses other HTML documents to fill in the spaces of the content. Each of the three HTML documents currently contains an "h1" tag that identifies what part of the document it is in. In its current state, it appears as follows:

Jinja Template Example

Now that we have this base template laid out, lets modify the imported files. header.html now looks like this:

<nav style="display: flex; flex-direction: row; justify-content: space-evenly; border: 2px solid gray;">
    <h1><a href="#">Item 1</a></h1>
    <h1><a href="#">Item 2</a></h1>
    <h1><a href="#">Item 3</a></h1>
    <h1><a href="#">Item 4</a></h1>
    <h1><a href="#">Item 5</a></h1>
</nav>

Enter fullscreen mode Exit fullscreen mode

the content file:


<div class="content" style="padding-top: 50px; display: flex; flex-direction: row; justify-content: space-evenly;">
    <div class="box1" style="width: 100px; height: 150px; border: 3px solid red;">
        <h4> 100 x 150 box</h4>
    </div>
    <div class="box2" style="width: 50px; height: 200px; border: 5px solid green;">
        <h4> 50 x 200 box</h4>
    </div>
    <div class="box3" style="width: 300px; height: 275px; border: 2px dotted yellow;">
        <h4> 300 x 275 box</h4>
    </div>   
</div>

Enter fullscreen mode Exit fullscreen mode

aaaaaaand the footer:


<footer style="margin-top: 50px; display: flex; justify-content: center; border: 2px solid gray;">
    <img src="{{ url_for('static', filename='sarah-and-duck.jpeg') }}">
</footer>

Enter fullscreen mode Exit fullscreen mode

Once the Jinja template is rendered via Flask, it looks like this:

Finished Jinja Template

So why should we care about this? We can put all of this on one page and not worry about imports and crap. Well, we care for the sake of modularity. Using this kind of templating engine allows us to assemble our web app in pieces that are independent of one another. Let's say something funky happens on your web server and the "header.html" file won't render. That would be REALLY annoying. But, the web page would still display, just minus the header. This would annoy your users, but they will not get the 404 that could potentially keep them from coming back the next time.

So, how do we remember the syntax of Jinja?

The easiest way is as follows: Each Jinja specific tag requires two symbols enclosing either the conditional (if, for, while) or variables. The opening and closing symbol is always a bracket "{" or "}". If you are asking Jinja to do something (like a conditional, loop, include, or block statement), the statement is framed by percent/modulo signs as well "%". If you are asking Jinja to say something (display a variable or an iterator in a loop), the item is wrapped in another set of brackets
"{", "}". That general rule of thumb applies to the vast majority of the plumbing of Flask. If you want to learn more specifics, check out the documentation which can be found here.

Leave a comment below if you have any questions or requests for future articles and I hope this has cleared up a bit of Jinja and Python web templates for you!

Top comments (1)

Collapse
 
fenix profile image
Fenix

thX for sharing !