Collect useful snippets of SQLAlchemy. Close session does not mean close database connection. SQLAlchemy session generally represents the transactions, not connections. Routing @app.route('/') def index: return 'Bad request', 400 from flask import rendertemplate @app.route('/assets') def assets: return rendertemplate. Flask: Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions. And before you ask: It’s BSD licensed! Web Development: Django: Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Web Development: Opencv.
2017-12-12T16:29:38Z
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.
- Chapter 2: Templates (this article)
Note 1: If you are looking for the legacy version of this tutorial, it's here.
Note 2: If you would like to support my work on this blog, or just don't have patience to wait for weekly articles, I am offering the complete version of this tutorial packaged as an ebook or a set of videos. For more information, visit courses.miguelgrinberg.com.
After you complete Chapter 1, you should have a fully working, yet simple web application that has the following file structure:
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 http://localhost:5000/ 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 Chapter 1 again before continuing.
The GitHub links for this chapter are: Browse, Zip, Diff.
What Are Templates?
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:
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:
app/routes.py: Return complete HTML page from view function
If you are not familiar with HTML, I recommend that you read HTML Markup 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:
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:
app/templates/index.html: Main page template
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:
app/routes.py: Use render_template() function
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 Jinja2 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.
Conditional Statements
You have seen how Jinja2 replaces placeholders with actual values during rendering, but this is just one of many powerful operations Jinja2 supports in template files. For example, templates also support control statements, given inside {% ... %}
blocks. The next version of the index.html template adds a conditional statement:
app/templates/index.html: Conditional statement in template
Now the template is a bit smarter. If the view function forgets to pass a value for the title
placeholder variable, then instead of showing an empty title the template will provide a default one. You can try how this conditional works by removing the title
argument in the render_template()
call of the view function.
Loops
The logged in user will probably want to see recent posts from connected users in the home page, so what I'm going to do now is extend the application to support that.
Once again, I'm going to rely on the handy fake object trick to create some users and some posts to show:
app/routes.py: Fake posts in view function
To represent user posts I'm using a list, where each element is a dictionary that has author
and body
fields. When I get to implement users and blog posts for real I'm going to try to preserve these field names as much as possible, so that all the work I'm doing to design and test the home page template using these fake objects will continue to be valid when I introduce real users and posts.
On the template side I have to solve a new problem. The list of posts can have any number of elements, it is up to the view function to decide how many posts are going to be presented in the page. The template cannot make any assumptions about how many posts there are, so it needs to be prepared to render as many posts as the view sends in a generic way.
For this type of problem, Jinja2 offers a for
control structure:
app/templates/index.html: for-loop in template
Simple, right? Give this new version of the application a try, and be sure to play with adding more content to the posts list to see how the template adapts and always renders all the posts the view function sends.
Template Inheritance
Python Flask Post
Most web applications these days have a navigation bar at the top of the page with a few frequently used links, such as a link to edit your profile, to login, logout, etc. I can easily add a navigation bar to the index.html
template with some more HTML, but as the application grows I will be needing this same navigation bar in other pages. I don't really want to have to maintain several copies of the navigation bar in many HTML templates, it is a good practice to not repeat yourself if that is possible.
Python Flask Examples
Jinja2 has a template inheritance feature that specifically addresses this problem. In essence, what you can do is move the parts of the page layout that are common to all templates to a base template, from which all other templates are derived.
So what I'm going to do now is define a base template called base.html
that includes a simple navigation bar and also the title logic I implemented earlier. You need to write the following template in file app/templates/base.html:
app/templates/base.html: Base template with navigation bar
In this template I used the block
control statement to define the place where the derived templates can insert themselves. Blocks are given a unique name, which derived templates can reference when they provide their content.
With the base template in place, I can now simplify index.html by making it inherit from base.html:
app/templates/index.html: Inherit from base template
Since the base.html template will now take care of the general page structure, I have removed all those elements from index.html and left only the content part. The extends
statement establishes the inheritance link between the two templates, so that Jinja2 knows that when it is asked to render index.html
it needs to embed it inside base.html
. The two templates have matching block
statements with name content
, and this is how Jinja2 knows how to combine the two templates into one. Now if I need to create additional pages for the application, I can create them as derived templates from the same base.html template, and that is how I can have all the pages of the application sharing the same look and feel without duplication.
Hello, and thank you for visiting my blog! If you enjoyed this article, please consider supporting my work on this blog on Patreon!
117 comments
#1Jim said 2017-12-12T19:17:52Z
#2Mayank Grover said 2017-12-14T04:47:52Z
#3Miguel Grinberg said 2017-12-14T07:07:42Z
#4Mbuvi said 2017-12-22T05:29:48Z
#5Calle said 2017-12-23T11:47:55Z
#6Gareth said 2017-12-23T20:32:41Z
#7Brett Vanderwerff said 2017-12-24T02:07:16Z
#8BinKhalid said 2017-12-24T10:22:11Z
#9jamescooper said 2017-12-29T11:02:22Z
#10Ben Moerman said 2018-02-14T03:00:37Z
#11John said 2018-02-19T12:27:38Z
#12Miguel Grinberg said 2018-02-19T18:36:25Z
#13Sandeep said 2018-02-21T14:55:37Z
#14Peter Skogberg said 2018-02-22T21:00:48Z
#15Bob said 2018-02-24T10:46:41Z
#16Miguel Grinberg said 2018-02-24T18:20:10Z
#17Zaymon said 2018-03-10T13:10:18Z
#18Miguel Grinberg said 2018-03-10T19:18:46Z
#19Josh Kim said 2018-03-12T01:34:54Z
#20Miguel Grinberg said 2018-03-12T02:51:01Z
#21Nodnarb said 2018-03-26T03:40:00Z
#22Miguel Grinberg said 2018-03-26T05:58:43Z
#23Tom Dixon said 2018-04-05T15:09:25Z
#24Bruno Fernandes said 2018-04-07T22:32:47Z
#25Claudiu said 2018-04-18T08:37:33Z
Leave a Comment
Resources for the second edition are here. I'd love to know what you think about Python Crash Course; please consider taking a brief survey. If you'd like to know when additional resources are available, you can sign up for email notifications here.
Python Flask App
Cheat sheets can be really helpful when you’re trying a set of exercises related to a specific topic, or working on a project. Because you can only fit so much information on a single sheet of paper, most cheat sheets are a simple listing of syntax rules. This set of cheat sheets aims to remind you of syntax rules, but also remind you of important concepts as well. You can click here and download all of the original cheat sheets in a single document.
An updated version of these sheets is also available through Leanpub and Gumroad. The updated version includes a sheet that focuses on Git basics, a printer-friendly b&w version of each sheet, and each sheet as a separate document. The updated versions are available at no cost on both platforms.
Python Flask Cheat Sheet Download
Individual Sheet Descriptions
- Beginner’s Python Cheat Sheet
- Provides an overview of the basics of Python including variables, lists, dictionaries, functions, classes, and more.
- Beginner’s Python Cheat Sheet - Lists
- Focuses on lists: how to build and modify a list, access elements from a list, and loop through the values in a list. Also covers numerical lists, list comprehensions, tuples, and more.
- Beginner’s Python Cheat Sheet - Dictionaries
- Focuses on dictionaries: how to build and modify a dictionary, access the information in a dictionary, and loop through dictionaries in a variety of ways. Includes sections on nesting lists and dictionaries, using an OrderedDict and more.
- Beginner’s Python Cheat Sheet - If Statements and While Loops
- Focuses on if statements and while loops: how to write conditional tests with strings and numerical data, how to write simple and complex if statements, and how to accept user input. Also covers a variety of approaches to using while loops.
- Beginner’s Python Cheat Sheet - Functions
- Focuses on functions: how to define a function and how to pass information to a function. Covers positional and keyword arguments, return values, passing lists, using modules, and more.
- Beginner’s Python Cheat Sheet - Classes
- Focuses on classes: how to define and use a class. Covers attributes and methods, inheritance and importing, and more.
- Beginner’s Python Cheat Sheet - Files and Exceptions
- Focuses on working with files, and using exceptions to handle errors that might arise as your programs run. Covers reading and writing to files, try-except-else blocks, and storing data using the json module.
- Beginner’s Python Cheat Sheet - Testing Your Code
- Focuses on unit tests and test cases. How to test a function, and how to test a class.
- Beginner’s Python Cheat Sheet - Pygame
- Focuses on creating games with Pygame. Creating a game window, rect objects, images, responding to keyboard and mouse input, groups, detecting collisions between game elements, and rendering text.
- Beginner’s Python Cheat Sheet - matplotlib
- Focuses on creating visualizations with matplotlib. Making line graphs and scatter plots, customizing plots, making multiple plots, and working with time-based data.
- Beginner’s Python Cheat Sheet - Pygal
- Focuses on creating visualizations with Pygal. Making line graphs, scatter plots, and bar graphs, styling plots, making multiple plots, and working with global datasets.
- Beginner’s Python Cheat Sheet - Django
- Focuses on creating web apps with Django. Installing Django and starting a project, working with models, building a home page, using templates, using data, and making user accounts.
Available from No Starch Press and Amazon.