Flask webserver - adding a detail view


Martin McBride, 2020-01-22
Tags template html
Categories flask sqlite

This article is part of a series on Flask.

We previously created a page which listed all the fruits in our database. This time we will create another page which displays the details for a particular fruit.

The template

Here is our database table, containing the name, colour and image file name for various fruits:

| name | color | image | |------|-------|-------| | Plum | Purple | plum.jpg | | Orange | Orange | orange.jpg | | Banana | Yellow | banana.jpg | | Strawberry | Red | strawberry.jpg |

You should copy the fruit images from github in the folder static to the static subfolder of your working folder.

To show the details of one fruit, we will require a new HTML template, this time we will call it fruit.html. Here is the code:

<html>
  <head>
    <link rel="stylesheet" href='/static/main.css' />
  </head>
  <body>
    <h1>{{name}}</h1>
    <img src="/static/{{image}}"> 
    Name: {{name}}
    Colour: {{color}}
  </body>
</html>

We list the name and colour of the fruit, also using the name as the page title. The image field contains the name of the file containing the fruit image, which we have placed in the static folder along with the css file. To display the image we use an img element:

<img src="static/{{image}}">

The Python code

We also need a new route function, which uses the route /fruit. But the question is, how will the function know which fruit to display?

A common technique, which we will use, is to include the identity of the subject in the URL. So to look at the details for plums we would use /fruit/Plum, for oranges /fruit/Orange, etc.

Here is how we implement this in Flask. We can use the route /fruit/. The function fruit is then passed the value name as a parameter:

@app.route('/fruit/<name>')
def fruit(name):
    con = sqlite3.connect('data.db')
    cur = con.cursor()    
    cur.execute("SELECT * FROM fruits where name = ?", (name,))
    rows = cur.fetchall()
    name = rows[0][0]
    color = rows[0][1]
    image = rows[0][2]

    return render_template('fruit.html', name=name,
                           color=color, image=image)

The rest of the code should be fairly familiar. Notice that the cur.execute() function can take a second parameter - a list (or tuple) of values. These are substituted into the SQL statement wherever there is a ? character so:

    cur.execute("SELECT * FROM fruits where name = ?", (name,))

produces this SQL statement (assuming name has the value "Plum"):

SELECT * FROM fruits where name = Plum

Since each database entry has a unique name, the query will only return one row. cur.fetchall() will return a list with a single entry, a tuple with the values for the selected fruit. For example for Plum rows would contain:

[('Plum', 'Purple', 'plum.jpg')]

Thus the name is rows[0][0], the color is rows[0][1], and the image is rows[0][3].

Updating the fruits page

The fruits page lists all the fruits, but it would be nice if those list items were links to the details page. We can do this quite easily by updating the fruits.html template:

<html>
  <head>
    <link rel="stylesheet" href='/static/main.css' />
  </head>
  <body>
    <h1>{{title}}</h1>
    {% for row in rows %}
      <a href="fruit/{{row[0]}}">{{row[0]}}</a></br>
    {% endfor %}
  </body>
</html>

We just use a link element for each list item:

    <a href="fruit/{{row[0]}}">{{row[0]}}</a></br>

Which becomes (for the plum item) :

    <a href="fruit/Plum"/>Plum</a></br>

The full code for this section and the previous section can be found on github.


Tag cloud

2d arrays abstract data type alignment and array arrays bezier curve built-in function close closure colour comparison operator comprehension context conversion data types design pattern device space dictionary duck typing efficiency encryption enumerate filter font font style for loop function function plot functools generator gif gradient html image processing imagesurface immutable object index input installing iter iterator itertools lambda function len linspace list list comprehension logical operator lru_cache mandelbrot map monad mutability named parameter numeric python numpy object open operator optional parameter or path positional parameter print pure function radial gradient range recursion reduce rotation scaling sequence slice slicing sound spirograph str stream string subpath symmetric encryption template text text metrics transform translation transparency tuple unpacking user space vectorisation webserver website while loop zip

Copyright (c) Axlesoft Ltd 2020