[Learn in 5 minutes] Code a web application with Flask (part 2)

Enrique Corona
3 min readMar 14, 2023

Now that we’ve built the basic API endpoints to manage books, let’s build a very simple front end taking advantage of some features of Flask and also using some basic Javascript with jQuery to illustrate how to use our REST APIs.

We need the following functionality in our UI.

  1. View a list of the books.
  2. Add new books to the list.
  3. Edit existing in the list.
  4. Delete books from the list.

Let’s start with the UI to view the list of the books. Flask uses Jinja2 templates out of the box, so we don’t have to configure anything, first let’s create a new endpoint to visualize the list.

from flask import render_template

@app.route('/frontend/list', methods=['GET'])
def uiListBooks():
return render_template('list.html', books=all_books.values())

Note that we are importing render_template which is used to render the template list.html and we’ll pass the object books with the list of all our books.

Now let’s create the template intemplates/list.html .

<!doctype html>
<title>List of books</title>
<h2>Books books books!</h2>
<table id="books">
<tr>
<th colspan="3"><a href="/frontend/add">Add a new book</a></th>
</tr>
<tr>
<th>Name</th>
<th>Author</th>
<th>Actions</th>
</tr>
{% for book in books -%}
<tr>
<td>{{book.name}}</td>
<td>{{book.author}}</td>
<td>
<a href="/frontend/edit?book_id={{book.uuid}}">Edit</a> |
<a href="/frontend/delete?book_id={{book.uuid}}">Delete</a>
</td>
</tr>
{%- endfor %}
</table>

Note that we use the variablebooks for templating, also note that we are creating links to 3 additional endpoints /frontend/add, /frontend/edit /frontend/delete , we’ll define these endpoints in the next article.

In the previous article we defined an API to get the list of the books (GET /books) and if you notice, we are not using it in this example, we are loading the list of books directly in GET /frontend/list , this is a valid approach, however if we want to load asynchronously the data we can invoke our API with Javascript from the html template.

First, let’s add a new endpoint that uses different template.

@app.route('/frontend/list_with_api', methods=['GET'])
def listBooksWithApi():
return render_template('list_with_api.html')

Next, let’s create a new template in templates/list_with_api.html

<!doctype html>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js">
</script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$.get('/books', function(books) {
Object.entries(books).forEach(([uuid, book]) => {
const row =
'<tr>' +
'<td>' + book.name + '</td>' +
'<td>' + book.author + '</td>' +
'<td> <a href="/frontend/edit?book_id=' + uuid + '">Edit</a> | <a href="/frontend/delete?book_id=' + uuid + '">Delete</a></td>' +
'</tr>';
$('#books').append(row);
});
});
});
</script>
<title>List of books</title>
<h2>Books books books!</h2>
<table id="books">
<tr>
<th colspan="3"><a href="/frontend/add">Add a new book</a></th>
</tr>
<tr>
<th>Name</th>
<th>Author</th>
<th>Actions</th>
</tr>
</table>

In this template.

  1. First we load jQuery from Google’s CDN.
  2. Next we call GET /books using jQuery to obtain a dictionary of books.
  3. Then we iterate through the entries of the dictionary to build a row of the table with each book.
  4. Finally we append each row to the main table.

Both approaches will render the same list of books.

Main page with the lIst of books

In the next article we’ll define the UI for adding and editing books as well as the functionality to delete them from the list.

Remember that this is a very simple toy example but now that you have the basic implementation you can make it more robust by adding input validation, error handling, etc…

Read the part 3.

--

--