Generic Excuse - Set Up A Flask API

2020-11/generic-excuse-flask.png

This blogpost will be the first part of a blog series where we will make a very simple web application using React and Flask.

In this part, we will build a Flask API to fetch excuses from a list of excuses on the backend. We have the option to get a random excuse or an excuse for a specific occasion like being late for work or skipping an occasion.

Set Up Project

  • Create a new folder for the project & create 2 sub folders frontend/ and backend/

mkdir generic-excuse

cd generic-excuse

mkdir frontend backend

  • Go in the backend folder, create a Python Environment and install Flask

cd backend

python -m venv .venv

source .venv/bin/activate

  • Install Flask

pip install flask

The Flask Server

  • Create a server.py file and paste the code below in it. This is a basic Flask boilerplate that will allow you to call the index route ('/') and it will return Hello, Fullstack Almanac!
 1from flask import Flask
 2
 3# Create a Flask Instance
 4app = Flask(__name__)
 5
 6# Add a route
 7@app.route('/')
 8def index():
 9    return "Hello, Fullstack Almanac!"
10
11# If you run this file, start the Flask instance
12if __name__ == '__main__':
13    app.run()

Retrieving An Excuse

  • In order to retrieve excuses, we first need to make some! Below I created an array with a few examples and a category that depicts the occasion an excuse can be used.
 1excuses = [
 2    {
 3        'category': 'late',
 4        'excuse': 'Sorry I\'m late, I was stuck in traffic'
 5    }, 
 6    {
 7        'category': 'late', 
 8        'excuse': 'I swear it wasn\'t my fault my neighbour forced me to stay in bed.'
 9    },
10    {
11        'category': 'skip_event',
12        'excuse': 'I can\'t come, I have to go fishing in the morning.'
13    },
14    {
15        'category': 'homework',
16        'excuse': 'My dog ate my homework.'
17    },
18    {
19        'category': 'homework',
20        'excuse': 'I didn\'t do my homework because this isn\'t the homework you\'re looking for'
21    }
22]
  • Next up we’ll create a flask route that will select a random excuse from the list and return it to the user.
1@app.route('/api/v1/excuse', methods=['GET'])
2def get_excuse():
3    return random.choice(excuses)
  • If we run our code again and go to localhost:5000/api/v1/excuse in the browser or call the URL with curl it will return a random excuse.

Command line showing the excuse api in action

Filter By Category

  • Next up we want to be able to filter by category. You might want to make a chatbot that gives you an excuse if you are late for work again.
  • First, we want to be able to use route parameters. This will allow us to call /api/v1/excuse/homework or /api/v1/excuse/late and use homework and late as a parameter for our function. We’ll default the parameter to random if none is given.
1@app.route('/api/v1/excuse', methods=['GET'])
2@app.route('/api/v1/excuse/<category>', methods=['GET'])
3def get_excuse(category='random'):
4    # ... Your logic will go here ...
  • When the category is random we just want to select a random excuse like before. But if the category is something else we’ll first create a smaller list of all the excuses in the same category
1@app.route('/api/v1/excuse', methods=['GET'])
2@app.route('/api/v1/excuse/<category>', methods=['GET'])
3def get_excuse(category='random'):
4    if category == 'random':
5        return jsonify(random.choice(excuses))
6    else:
7        return jsonify(random.choice([excuse for excuse in excuses if excuse['category'] == category]))
  • The line random.choice([excuse for excuse in excuses if excuse['category'] == category]) might be a bit confusing. It adds an excuse to an array for every excuse in excuses that has the same category. You could write it out more like this:
1filtered_excuses = []
2for excuse in excuses:
3    if (excuse['category'] == category):
4        filtered_excuses.append(excuse)
5return jsonify(random.choice(filtered_excuses))
  • Now if you run the code you will be able to get a random excuse for every category.

Command line showing the filtered results

This is it for the API code, we are now able to fetch excuses from our API based on the occasion. In the next blog post, we will build a React Frontend to consume this API so that users can interact with it.

You can find the code below or on Github.

 1import random
 2from flask import Flask, jsonify
 3
 4app = Flask(__name__)
 5
 6excuses = [
 7    {
 8        'category': 'late',
 9        'excuse': 'Sorry I\'m late, I was stuck in traffic'
10    }, 
11    {
12        'category': 'late', 
13        'excuse': 'I swear it wasn\'t my fault my neighbour forced me to stay in bed.'
14    },
15    {
16        'category': 'skip_event',
17        'excuse': 'I can\'t come, I have to go fishing in the morning.'
18    },
19    {
20        'category': 'homework',
21        'excuse': 'My dog ate my homework.'
22    },
23    {
24        'category': 'homework',
25        'excuse': 'I didn\'t do my homework because this isn\'t the homework you\'re looking for'
26    }
27]
28
29@app.route('/api/v1/excuse', methods=['GET'])
30@app.route('/api/v1/excuse/<category>', methods=['GET'])
31def get_excuse(category='random'):
32    if category == 'random':
33        return jsonify(random.choice(excuses))
34    else:
35        return jsonify(random.choice([excuse for excuse in excuses if excuse['category'] == category])) 
36
37if __name__ == '__main__':
38    app.run()