💾 Archived View for mozz.us › files › flask_mega_tutorial_part_2.gmi captured on 2022-07-16 at 14:20:58. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2020-09-24)
-=-=-=-=-=-=-
In this second installment of the Flask Mega-Tutorial series, I'm going to discuss how to work with templates.
For your reference, below is a list of the articles in this series.
After you complete
you should have a fully working, yet simple web application that has the following file structure:
microblog\ venv\ app\ __init__.py routes.py microblog.py
To run the application you set the FLASK_APP=microblog.py in your terminal session, and then execute flask run. This starts a web server with the application, which you can open by typing the
URL in your web browser's address bar.
In this chapter you will continue working on the same application, and in particular, you are going to learn how to generate more elaborate web pages that have a complex structure and many dynamic components. If anything about the application or the development workflow so far isn't clear, please review
again before continuing.
The GitHub links for this chapter are:
I want the home page of my microblogging application to have a heading that welcomes the user. For the moment, I'm going to ignore the fact that the application does not have the concept of users yet, as this is going to come later. Instead, I'm going to use a mock user, which I'm going to implement as a Python dictionary, as follows:
user = {'username': 'Miguel'}
Creating mock objects is a useful technique that allows you to concentrate on one part of the application without having to worry about other parts of the system that don't exist yet. I want to design the home page of my application, and I don't want the fact that I don't have a user system in place to distract me, so I just make up a user object so that I can keep going.
The view function in the application returns a simple string. What I want to do now is expand that returned string into a complete HTML page, maybe something like this:
from app import app @app.route('/') @app.route('/index') def index(): user = {'username': 'Miguel'} return ''' <html> <head> <title>Home Page - Microblog</title> </head> <body> <h1>Hello, ''' + user['username'] + '''!</h1> </body> </html>'''
If you are not familiar with HTML, I recommend that you read
on Wikipedia for a brief introduction.
Update the view function as shown above and give the application a try to see how it looks in your browser.
I hope you agree with me that the solution used above to deliver HTML to the browser is not good. Consider how complex the code in this view function will become when I have the blog posts from users, which are going to constantly change. The application is also going to have more view functions that are going to be associated with other URLs, so imagine if one day I decide to change the layout of this application, and have to update the HTML in every view function. This is clearly not an option that will scale as the application grows.
If you could keep the logic of your application separate from the layout or presentation of your web pages, then things would be much better organized, don't you think? You could even hire a web designer to create a killer web site while you code the application logic in Python.
Templates help achieve this separation between presentation and business logic. In Flask, templates are written as separate files, stored in a templates folder that is inside the application package. So after making sure that you are in the microblog directory, create the directory where templates will be stored:
(venv) $ mkdir app/templates
Below you can see your first template, which is similar in functionality to the HTML page returned by the index() view function above. Write this file in app/templates/index.html:
<html> <head> <title>{{ title }} - Microblog</title> </head> <body> <h1>Hello, {{ user.username }}!</h1> </body> </html>
This is a mostly standard, very simply HTML page. The only interesting thing in this page is that there are a couple of placeholders for the dynamic content, enclosed in {{ ... }} sections. These placeholders represent the parts of the page that are variable and will only be known at runtime.
Now that the presentation of the page was offloaded to the HTML template, the view function can be simplified:
from flask import render_template from app import app @app.route('/') @app.route('/index') def index(): user = {'username': 'Miguel'} return render_template('index.html', title='Home', user=user)
This looks much better, right? Try this new version of the application to see how the template works. Once you have the page loaded in your browser, you may want to view the source HTML and compare it against the original template.
The operation that converts a template into a complete HTML page is called rendering. To render the template I had to import a function that comes with the Flask framework called render_template(). This function takes a template filename and a variable list of template arguments and returns the same template, but with all the placeholders in it replaced with actual values.
The render_template() function invokes the
template engine that comes bundled with the Flask framework. Jinja2 substitutes {{ ... }} blocks with the corresponding values, given by the arguments provided in the render_template() call.