Reading row[2] works, but nothing in it says "price". And if someone changes the order of the columns in the SELECT, every index silently points at the wrong value.
A connection can make smarter rows. Set its row_factory to sqlite3.Row, and every row it returns from then on also knows its column names: row["price"] works, and dict(row) turns the whole row into a dictionary whose keys are the column names. For example, with a table books:
library = sqlite3.connect("library.db")
library.row_factory = sqlite3.Row
rows = library.execute("SELECT title, year FROM books").fetchall()
first = rows[0]
print(first["title"]) # Dune
print(dict(first)) # {'title': 'Dune', 'year': 1965}
Since the code no longer depends on the order of the columns, the query can ask for all of them with SELECT *. The products' stock comes along too.
GET / → 200 Welcome to the shop!
GET /products → 200 [{"id": 1, "name": "Mug", "price": 12, "category": "kitchen", "stock": 10},
{"id": 2, "name": "Notebook", "price": 7, "category": "office", "stock": 0},
… 8 products in all …
{"id": 8, "name": "Gift card", "price": 50, "category": null, "stock": 999}]
Your task: give db rows that know their column names, ask for every column of products, and build each product with dict(row) instead of index numbers.
Assignment
Follow the Coding Tutorial to switch the shop to named rows and SELECT *.
Hint
Set db.row_factory right after the line that opens db, so every row the connection returns has its column names. Then dict(row) needs no keys from you.
Free plan: 30 tutor messages. PRO is unlimited.
