-
Notifications
You must be signed in to change notification settings - Fork 4
db4
In this lesson we will build a nicer view of our blog entries, rather than the "dump" output which is ugly.
First, let's create a new HTML template (our first one for the blog!). Inside the templates/ subfolder, create a file called browse.html:
<html>
<head>
<title>Browse entries</title>
</head>
<body>
<h1>Browse entries</h1>
{% for entry in entries %}
Title: {{ entry.title }}<br>
Date: {{ entry.date }}<br>
Content: {{ entry.content }}<p>
{% else %}
This blog is empty.
{% endfor %}
</body>
</html>To be clear, our directory structure now looks like
blog/
+-- blog.py
+-- schema.sql
+-- populate.sql
+-- templates/
+-- browse.html
Let's also add a new route to our blog.py code:
@app.route("/browse")
def browse():
db = get_db()
cursor = db.cursor()
cursor.execute('select id, date, title, content from entries order by date')
rowlist = cursor.fetchall()
return render_template('browse.html', entries=rowlist)Use web preview to visit http://blahblah.appspot.com/browse. You should see your blog entries!

The Flask route for /browse isn't all that different than /dump, though we will move the processing of the SQL rows to the HTML template. Here, we connect
to the database, execute the query, turn the rows iterator into a list, and send that list to render_template. The only new thing is we've never seen render_template called with a keyword argument other than a simple integer or string.
Here, rowlist is a list of SQL rows. So how does the template handle this? Let's flip to the HTML template and see.
In the HTML template, notice the main logic is a for loop.
Inside the loop, we mingle HTML code with variable insertions using double curly braces. The entry variable is a dictionary, and you can do lookups in three different ways (with a dot or with square brackets, single or double braces). They all work the same way, just pick your favorite and stick with it.
Some explanation is warranted for the else part after the for loop. You may have not seen else attached to a for loop before. What this means is that if the for loop never executed (there were zero entries), then the else block runs. If the for loop runs at least once, the else block is skipped. So we use the else block to print out a message saying the blog is empty.
To see what happens when the blog is empty, go to the command line and stop Flask with Control-C. Then type flask initdb to reset the database. Then restart Flask with flask run. If you visit http://blahblah.appspot.com/browse, you should see the empty blog message. Now go back to the command line and re-populate the database with flask populate. Back in the web browser, reloading will bring back the list of blog entries.
We can use an unordered list to format our entries more nicely. The HTML syntax (as a reminder) looks like
<ul>
<li>first item
<li>second item
<li>third item
</ul>This will be easy to add to our template; we just need to put <li> in front of each blog entry inside the for loop.
There is a caveat, however: where do we put the <ul> and </ul> tags? We can't put them inside the for loop because then they would get printed once for every blog entry. Instead, what we'll do is add an if test that detects whether the entries variable has any rows in it:
<html>
<head>
<title>Browse entries</title>
</head>
<body>
<h1>Browse entries</h1>
{% if entries|length > 0 %}
<ul>
{% for entry in entries %}
<li>Title: {{ entry.title }}<br>
Date: {{ entry.date }}<br>
Content: {{ entry.content }}<p>
{% endfor %}
</ul>
{% else %}
This blog is empty.
{% endif %}
</body>
</html>Modify the HTML template so that the blog entries look like the formatting below:

Specifically, make the titles bold, put the date in parentheses, put the content below with a blank line in between, and separate the entries with a horizontal rule (<hr>).
Check below for the answer.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
<html>
<head>
<title>Browse entries</title>
</head>
<body>
<h1>Browse entries</h1>
{% if entries|length > 0 %}
<ul>
{% for entry in entries %}
<li><b>{{ entry.title }}</b> ({{ entry.date }})
<p>
{{ entry.content }}
<hr>
{% endfor %}
</ul>
{% else %}
This blog is empty.
{% endif %}
</body>
</html>Use the main wiki page to navigate, not the list of pages directly above, because those are out of order.