Flask Guide - Part 2. Templates

Categories:   web development  
Tags:   python   flask  

This is part 2 of the “Flask Guide”.

You can check the previous post here.

We’ll cover more in the next post.

Credits

These are the sources I used:

Templates

This section will cover:

  • templates

Creating templates

  • create templates folder:
mkdir static
mkdir templates
touch templates/home.html
touch templates/about.html
touch templates/layout.html
touch static/main.css

The project folder should now look like:

.venv
static/main.css
templates/layout.html
templates/home.html
templates/about.html
begin.py
requirements.txt
  • We will put the main html in layout.html. The other templates will inherit from this file.
  • We will use render_template and url_for so let’s update the begin.py file:
from flask import Flask, render_template, url_for
app = Flask(__name__)

posts = [
    {
        'author': 'John Doe',
        'title': 'Blog Post 1',
        'content': 'First post content',
        'date_posted': '2019, Nov 21'
    },
    {
        'author': 'Jane Doe',
        'title': 'Blog Post 2',
        'content': 'Second post content',
        'date_posted': '2019, Nov 22'
    }
]

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

@app.route("/about")
def about():
    return render_template('about.html', title='About')

if __name__ == '__main__':
    app.run(debug=True)
  • Let’s deal with the CSS file. main.css:
body {
    background: #fafafa;
    color: #333333;
    margin-top: 5rem;
  }

  h1, h2, h3, h4, h5, h6 {
    color: #444444;
  }

  .bg-steel {
    background-color: #5f788a;
  }

  .site-header .navbar-nav .nav-link {
    color: #cbd5db;
  }

  .site-header .navbar-nav .nav-link:hover {
    color: #ffffff;
  }

  .site-header .navbar-nav .nav-link.active {
    font-weight: 500;
  }

  .content-section {
    background: #ffffff;
    padding: 10px 20px;
    border: 1px solid #dddddd;
    border-radius: 3px;
    margin-bottom: 20px;
  }

  .article-title {
    color: #444444;
  }

  a.article-title:hover {
    color: #428bca;
    text-decoration: none;
  }

  .article-content {
    white-space: pre-line;
  }

  .article-img {
    height: 65px;
    width: 65px;
    margin-right: 16px;
  }

  .article-metadata {
    padding-bottom: 1px;
    margin-bottom: 4px;
    border-bottom: 1px solid #e3e3e3
  }

  .article-metadata a:hover {
    color: #333;
    text-decoration: none;
  }

  .article-svg {
    width: 25px;
    height: 25px;
    vertical-align: middle;
  }

  .account-img {
    height: 125px;
    width: 125px;
    margin-right: 20px;
    margin-bottom: 16px;
  }

  .account-heading {
    font-size: 2.5rem;
  }

Let’s finish by changing our template files.

  • layout.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css' ) }}">

    {% if title %}
        <title>Flask Blog - {{ title }}</title>
    {% else %}
        <title>Flask Blog</title>
    {% endif %}
</head>
<body>
    <header class="site-header">
        <nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
            <div class="container">
            <a class="navbar-brand mr-4" href="/">Flask Blog</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarToggle">
                <div class="navbar-nav mr-auto">
                <a class="nav-item nav-link" href="/">Home</a>
                <a class="nav-item nav-link" href="/about">About</a>
                </div>
                <!-- Navbar Right Side -->
                <div class="navbar-nav">
                <a class="nav-item nav-link" href="/login">Login</a>
                <a class="nav-item nav-link" href="/register">Register</a>
                </div>
            </div>
            </div>
        </nav>
    </header>
    <main role="main" class="container">
        <div class="row">
            <div class="col-md-8">
            {% block content %}{% endblock %}
            </div>
            <div class="col-md-4">
            <div class="content-section">
                <h3>Our Sidebar</h3>
                <p class='text-muted'>You can put any information here you'd like.
                <ul class="list-group">
                    <li class="list-group-item list-group-item-light">Latest Posts</li>
                    <li class="list-group-item list-group-item-light">Announcements</li>
                    <li class="list-group-item list-group-item-light">Calendars</li>
                    <li class="list-group-item list-group-item-light">etc</li>
                </ul>
                </p>
            </div>
            </div>
        </div>
    </main>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>
  • home.html:
{% extends "layout.html" %}
{% block content %}   
    {% for post in posts %}
        <article class="media content-section">
            <div class="media-body">
                <div class="article-metadata">
                <a class="mr-2" href="#">{{ post.author }}</a>
                <small class="text-muted">{{ post.date_posted }}</small>
                </div>
                <h2><a class="article-title" href="#">{{ post.title }}</a></h2>
                <p class="article-content">{{ post.content }}</p>
            </div>
        </article>
    {% endfor %}
{% endblock content %}   
  • about.html:
{% extends "layout.html" %}
{% block content %}   
    <h1>About Page</h1>
{% endblock content %}

Summary

  • We created a layout.html file with a {% block content %}{% endblock %}
  • We then have home.html & about.html files that extends the layout.html file.
  • Each file also has the {% block content %} which overrides the content.
  • We imported render_template and url_for from flask.
  • We passed in variables with render_template.
  • We made a for loop in the home.html file that uses the variables from the begin.py file.
  • We imported some styles from bootstrap and added some html classes.
  • Using templates will reduce duplication of our html code.

I think we will end this section here.

We’ll cover more in the next post.

Related Products



Categories:   web development  
Tags:   python   flask