Written by Sümeyye Sever (notes I took while learning Python)


Jinja is a templating engine for Python, commonly used in web development with frameworks like Flask. It allows developers to dynamically generate HTML or other text-based formats by embedding Python expressions and control structures within template files.

Key Features of Jinja:

  1. Dynamic Content: You can insert variables into templates and display dynamic data.

    <h1>Hello, {{ name }}!</h1>
    

    If name=”Oikawa” the rendered template will show:

    <h1>Hello, Sumeyye!</h1>
    
  2. Control Structures: Jinja supports loops and conditionals for more complex logic in templates.

    <ul>
        {% for item in items %}
        <li>{{ item }}</li>
        {% endfor %}
    </ul>
    
    

    If items=[”Apple”, “Banana”, “Cherry”] the output will be:

    <ul>
        <li>Apple</li>
        <li>Banana</li>
        <li>Cherry</li>
    </ul>
    
  3. Filters: Modify data using built-in filters or custom ones.

    {{ "hello world" | upper }}  <!-- Output: HELLO WORLD -->
    
  4. Macros and Inheritance:

    Base template:

    <!DOCTYPE html>
    <html>
    <head>
        <title>{% block title %}Default Title{% endblock %}</title>
    </head>
    <body>
        {% block content %}{% endblock %}
    </body>
    </html>
    

    Extended template:

    {% extends "base.html" %}
    {% block title %}Home Page{% endblock %}
    {% block content %}
    <h1>Welcome to my website!</h1>
    {% endblock %}
    
  5. Safe and Secure: Jinja escapes variables by default to prevent XSS attacks.

Code Example

Blog Website Project Part 1

main.py:

from flask import Flask, render_template
import requests

app = Flask(__name__)

posts = requests.get("<https://api.npoint.io/43e3b809cdcf1eef9e41>").json()
print(posts)

@app.route('/')
def home():
    return render_template("index.html", posts=posts)

# The posts variable is passed to the template, making it available for use in the HTML file 
# (e.g., for dynamically displaying the fetched posts).

@app.route('/post/<int:post_id>')
def get_post(post_id):
    the_post = {}
    for post in posts:
        if post["id"] == post_id:
            the_post = post
    return render_template("post.html", post=the_post)

if __name__ == "__main__":
    app.run(debug=True)

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="<https://fonts.googleapis.com/css2?family=Raleway>" rel="stylesheet">
    <link rel="stylesheet" href="../static/css/styles.css">
</head>
<body>
<div class="wrapper">
    <div class="top">
        <div class="title"><h1>My Blog</h1></div>
    </div>
    {% for post in posts %}
    <div class="content">
        <div class="card">
            <h2>{{post.title}}</h2>
            <p class="text">{{post.subtitle}} </p>
            <a href="{{ url_for('get_post', post_id = post.id) }}">Read</a>
        </div>
    </div>
    {% endfor %}

</div>
</body>
<footer>
    <p>♥️</p>
</footer>
</html>

post.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="<https://fonts.googleapis.com/css2?family=Raleway>" rel="stylesheet">
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
    <!-- this is the best way to link css file when using jinja-->
</head>
<body>
<div class="wrapper">
    <div class="top">
        <div class="title"><h1>My Blog</h1></div>
           </div>
        <div class="content">
            <div class="card">
                <h1>{{ post.title }}</h1>
                <h2>{{ post.subtitle }}</h2>
                <p>{{ post.body }}</p>
            </div>

    </div>
</div>
</body>
<footer>
    <p>♥️</p>
</footer>
</html>