1. Within your “realpython” directory create a “flask-blog” directory.
2. Create and activate a virtualenv.
3. Make sure to place your app under version control by adding a Git repo.
4. Set up the following files and directories:
1 ���
2 blog.py���
3 static�
4 ��� css�
5 ��� img�
6 ��� js���
7 templates
First, all of the logic (Python/Flask code) goes in theblog.pyfile. Our “static” direc-tory holds static files like Javascript files, CSS stylesheets, and images. Finally, the
“template” folder houses all of our HTML files.
The important thing to note is that theblog.pyacts as the application controller. Flask works with a client-server model. The server receives HTTP requests from the client (i.e., the web browser), then returns content back to the client in the form of a response:
NOTE: HTTP is the method used for all web-based communications; the
‘http://’ that prefixes URLs designates an HTTP request. Literally every-thing you see in your browser is transferred to you via HTTP.
5. Install flask:
1 pip install flask
Let’s build our app!
Figure 7.1: HTTP request/response Cycle
Model
Our database has one table calledpostswith two fields -titleandpost. We can use the follow-ing script to create and populate the database:
1 # sql.py - Create a SQLite3 table and populate it with data
2 3
4 import sqlite3
5
6 # create a new database if the database doesn't already exist
7 with sqlite3.connect("blog.db") as connection:
8
9 # get a cursor object used to execute SQL commands
10 c = connection.cursor()
11
12 # create the table
13 c.execute("""CREATE TABLE posts
14 (title TEXT, post TEXT)
15 """)
16
17 # insert dummy data into the table
18 c.execute('INSERT INTO posts VALUES("Good", "I\'m good.")')
19 c.execute('INSERT INTO posts VALUES("Well", "I\'m well.")')
20 c.execute('INSERT INTO posts VALUES("Excellent", "I\'m excellent.")')
21 c.execute('INSERT INTO posts VALUES("Okay", "I\'m okay.")') Save the file within your “flask-blog” directory. Run it. This reads the database definition provided in sql.pyand then creates the actual database file and adds a number of entries.
Check the SQLite Browser to ensure the table was created correctly and populated with data.
Notice how we escaped the apostrophes in the INSERT statements.
Controller
Like the controller in the hello_world app (app.py), this script will define the imports, con-figurations, and each view.
1 # blog.py - controller
2 3
4 # imports
5 from flask import Flask, render_template, request, session, \
6 flash, redirect, url_for, g
7 import sqlite3
14 # pulls in app configuration by looking for UPPERCASE variables
15 app.config.from_object(__name__)
16
17 # function used for connecting to the database
18 def connect_db():
19 return sqlite3.connect(app.config['DATABASE'])
20
21 if __name__ == '__main__':
22 app.run(debug=True)
Save this file asblog.pyin your main project directory. Theconfigurationsection is used for defining application-specific settings.
Make sure you understand how this is working:
1 # configuration
2 DATABASE = 'blog.db'
3
4 ...snip...
5
6 # pulls in app configuration by looking for UPPERCASE variables
NOTE: Stop. You aren’t cheating and using copy and paste, are you?… Good!
Views
After a user logs in, s/he is redirected to the main blog homepage where all posts are displayed.
Users can also add posts from this page. For now, let’s get the page set up, and worry about the functionality later.
1 {% extends "template.html" %}
2 {% block content %}
3 <h2>Welcome to the Flask Blog!</h2>
4 {% endblock %}
We also need a login page:
1 {% extends "template.html" %}
2 {% block content %}
3 <h2>Welcome to the Flask Blog!</h2>
4 <h3>Please login to access your blog.</h3>
5 <p>Temp Login: <a href="/main">Login</a></p>
6 {% endblock %}
Save these files as main.html andlogin.html, respectively, in the “templates” directory. I know you have questions about the strange syntax - i.e.,{% extends "template.html"%}
- in both these files. We’ll get to that in just a second.
Now updateblog.pyby adding two new functions for the views:
1 @app.route('/')
1 # blog.py - controller
2 3
4 # imports
5 from flask import Flask, render_template, request, session, \
8
9 # configuration
10 DATABASE = 'blog.db'
11
12 app = Flask(__name__)
13
14 # pulls in configurations by looking for UPPERCASE variables
15 app.config.from_object(__name__)
16
17 # function used for connecting to the database
18 def connect_db():
19 return sqlite3.connect(app.config['DATABASE'])
20
21 @app.route('/')
22 def login():
23 return render_template('login.html')
24
25 @app.route('/main')
26 def main():
27 return render_template('main.html')
28
29 if __name__ == '__main__':
30 app.run(debug=True)
In the first function,login(), we mapped the URL/to the function, which in turn sets the route tologin.htmlin the templates directory. How about themain()function? What’s going on there? Explain it to yourself. Say it out loud.
Templates
Templates (template.html, in our case) are HTML skeletons that serve as the base for either your entire website or pieces of your website. They eliminate the need to code the basic HTML structure more than once. Separating templates from the main business logic (blog.py) helps with the overall organization.
Further, templates make it much easier to combine HTML and Python in a programmatic-like manner.
Let’s start with a basic template:
1 <!DOCTYPE html>
Save this astemplate.htmlwithin your templates directory.
There’s a relationship between the parent, template.html, and child templates, login.html andmain.html. This relationship is called template inheritance. Essentially, our child tem-plates extend, or are a child of,template.html. This is achieved by using the{% extends
"template.html"%}tag. This tag establishes the relationship between the template and views.
So, when Flask rendersmain.htmlit must first rendertemplate.html.
You may have also noticed that both the parent and child template files have identical block tags: {% block content %} and{% endblock %}. These define where the child tem-plates, login.htmlandmain.html, are filled in on the parent template. When Flask renders the parent template,template.html, the block tags are filled in with the code from the child templates:
Code found between the {% %} tags in the templates is a subset of Python used for basic
Figure 7.2: Parent and Child Jinja2 templates
SEE ALSO: The are a number of differenttemplatingformats. Flask by default usesJinja2 as its templating engine. Read more about Jinja2 templating fromthisblog post.