Now that we’re able to display a list of all the items on the shopping list, the next step is to be able to display single items. This will lead us into being able to update these items, too.
7. Displaying a single item
7.1 Explanation
What we’re going to do is create a new webpage for each item on the webpage. The URL for the HTML will be 127.0.0.1:5000/1 for the first item (as it has an ID of 1), and so on for all the remaining items. This means that we will need to create a new flask route with this value.
7.2 Working on the get_item() function
We’re going to start by creating a function called get_item(). We will pass it an ID (from the database) and then receive back the item associated with that ID. If there is no ID, Flask will respond with a page does not exist.
For the 404 (page does not exist), we can make use of Wekzeug’s library, and specifically the abort function.
import sqlite3
from flask import Flask, render_template
from werkzeug.exceptions import abort
Then add the get_item() function:
def get_db_connection():
conn = sqlite3.connect(‘database.db’)
conn.row_factory = sqlite3.Row
return conn
def get_item(item_id):
conn = get_db_connection()
item = conn.execute(‘SELECT * FROM items WHERE id = ?’, (item_id,)).fetchone()
conn.close()
if item is None:
abort(404)
return item
This function has an item_id argument that is opposed into it. This tells it what item to return. We open a database connection, then execute an SQL query to get the item associated with the item_id value. We use fetchone() and store it in the item variable, then close the connection. If the value is None, we use the abort() function.
7.3 Adding the view function
Now lets add a view function to app.py. This will use a variable rule to specify the item id that will need to be accessed it. Basically, the decorator is saying it is any positive integer that we need to access in the item function. Then the item function is created. It uses the get_item function to get the item_id and information from the database, and then renders the item.html template.
@app.route(‘/<int:item_id>’)
def item(item_id):
item = get_item(item_id)
return render_template(‘item.html’, item=item)
7.4 Creating a new template for item.html
The final part is creating the template to be rendered. In this case, we have to make sure that we use the variables we passed in so that the right content is displayed.
{% extends ‘base.html’ %}
{% block content %}
<h2>{% block title %} {{ item[‘item’] }} {% endblock %}</h2>
<span class=”badge badge-primary”>{{ item[‘created’] }}</span>
<p>{{ item[‘description’] }}</p>
<p>{{ item[‘store’] }}</p>
<p>{{ item[‘price’] }}</p>
<p>{{ item[‘purchased’] }}</p>
{% endblock %}
7.5 Linking it together
At the moment, the URLS work, but we need to make sure that links on the index page work as well. Back in index.html ,we need to change it to look like this:
{% for post in posts %}
<a href=”{{ url_for(‘item’, item=item[‘id’]) }}”>
<h2>{{ item[‘item’] }}</h2>
</a>
<span class=”badge badge-primary”>{{ item[‘created’] }}</span>
<hr>
{% endfor %}