Send the club's data as JSON, so other programs (an app, a game, another website) can read it: routes that return data instead of pages.
Weather apps, maps and music players get their data from APIs: addresses that send back data for programs, not pages for people.
A page is for people to read. An API is for programs: it sends back data. In Flask, a route that returns a dictionary sends it as JSON, a text format almost every language can read. The App tab shows JSON neatly; another program would turn it straight back into a dictionary or list.
Make your prediction first. Help opens once you've locked it in.
from flask import Flask
app = Flask(__name__)
@app.route("/api/club")
def club():
return {"name": "Chess club", "room": 12, "days": ["Tuesday", "Thursday"]}
app.run()
The function returns a dictionary, not HTML. What does Flask send?
Run it and follow the links, then try /api/members/Champions and /api/members/Nobody in the address bar. The members come from members.csv, so anyone who joined last lesson is here too.
import csv
from flask import Flask, request
app = Flask(__name__)
def load_members():
with open("members.csv") as f:
return list(csv.DictReader(f))
@app.route("/")
def home():
page = "<h1>Chess club API</h1>"
page = page + "<p><a href='/api/members'>/api/members</a></p>"
page = page + "<p><a href='/api/members/Players'>/api/members/Players</a></p>"
return page
@app.route("/api/members")
def api_members():
return {"members": load_members()}
@app.route("/api/members/<group>")
def api_group(group):
found = []
for m in load_members():
if m["group"] == group:
found.append(m)
return {"group": group, "count": len(found), "members": found}
app.run()
import csv
from flask import Flask, request
app = Flask(__name__)
def load_members():
with open("members.csv") as f:
return list(csv.DictReader(f))
@app.route("/")
def home():
page = "<h1>Chess club API</h1>"
page = page + "<p><a href='/api/members'>/api/members</a></p>"
page = page + "<p><a href='/api/members/Players'>/api/members/Players</a></p>"
return page
@app.route("/api/members")
def api_members():
return {"members": load_members()}
@app.route("/api/members/<group>")
def api_group(group):
found = []
for m in load_members():
if m["group"] == group:
found.append(m)
return {"group": group, "count": len(found), "members": found}
app.run()
Why an app wants JSON.
What a program gets when nothing matches.
A function that was never run.
Visiting /api/members gives 500 Internal Server Error. Click the line that is wrong.
Add /api/stats, which sends the number of members in each group.
Count the members of each group in a dictionary (as in Data detective's bar chart) and return the dictionary.
Let /api/members?name=ad send only the members whose name contains ad (any capitals). The part after ? is the query string; request.args.get("name", "") reads it.
An address can end with ?name=ad. request.args.get("name", "") gives "ad" (or "" if there is none).
Keep the members whose name contains it: if name in m["name"].lower():
Add /api/stats, which sends how many members each group has.
Run your program. This ticks when your code does all of the above.
Let /api/members?name=ad find members whose name contains ad.
Run your program. This ticks when your code does all of the above.
Make an API for results.csv: /api/results sends every row, and /api/leader sends the player with the most wins and how many. Send wins as numbers, not text.
Make an API for results.csv: /api/results with every row, and /api/leader with the player who has the most wins.
Run your program. This ticks when your code does all of the above.
The optional last lesson builds the same API in FastAPI, where the types of each input are checked for you.
Students turn the club's data into an API, with routes that return dictionaries sent as JSON, then add a stats route, a search with a query string and an API of their own for the results. About 45 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
Read the unit primer first. A Flask route that returns a dictionary sends it as JSON (Flask sorts the keys); the App tab shows it neatly. An API is a set of addresses that send data for programs, not pages for people. The lesson reads members.csv from Lesson 4 (the Files tab can put the original back). The bug task returns the function load_members instead of calling it, giving 500 Internal Server Error (the console shows the error: a function cannot be sent as JSON). The query string (?name=ad) is read with request.args.get("name", ""), where the second value is used when it is missing. The info question raises privacy: an API shares data with anyone who asks.
Seeing JSON as data for programs, not a page. Ask how another program would use the reply, before adding routes.
Stretch: Add /api/members/<group>/count that sends only a number, and explain why a program might want that.
Support: Give students the stats loop, and ask them only to write the route and the return.
The optional FastAPI lesson builds the same API with type checks done for you. Data detective's optional API lesson calls real APIs such as Wikidata.