Start learning free

LESSON 132 OF 188 · BACKEND: SPEED

Project: A Fast Product List in Python

Practice

This project puts the module together in the shop's busiest route, GET /products. Earlier lessons made the list ask only for id, name, price and read one keyset page at a time with ?after=. Two things are still missing: clients can't choose the page size, and the list lost its cache when it got pages.

A size with a limit: clients will pick the size with ?size=, but only up to a limit. Without one, a single request for ?size=1000000 reads and sends the whole table, and the pages were for nothing. Read the number with a default, and refuse anything out of range with 400, like this route for reviews does:

@app.get("/reviews")
def get_reviews():
    count = request.args.get("count", 10, type=int)
    if count < 1 or count > 20:
        return jsonify({"error": "count must be between 1 and 20"}), 400
    ...

One cache entry per page: a single key like "products" would hand out the first cached page for every page. Each page needs its own cache key, built from everything that decides its content: after and size, as in "products:6:3". The routes that change products already call cache.clear(), which forgets every page at once.

On a fresh shop, these requests, in this order, must get these answers:

GET /products  →  200  {"next_after": 3, "products": [{"id": 1, "name": "Mug", "price": 12}, …]}
GET /products?size=5  →  200  {"next_after": 5, "products": [… 5 products, ids 1 to 5 …]}
GET /products?after=6  →  200  {"next_after": null, "products": [{"id": 7, "name": "Stapler", …}, {"id": 8, …}]}
GET /products?after=6  →  200  the same page, from the cache
GET /debug/queries  →  200  {"queries": 3}
POST /products {"name": "Cup", "price": 8}  →  201  {"id": 9, "name": "Cup", "price": 8}
GET /products?after=6  →  200  {"next_after": 9, "products": [{"id": 7, …}, {"id": 8, …}, {"id": 9, "name": "Cup", "price": 8}]}
GET /products?size=6  →  400  {"error": "size must be between 1 and 5"}
GET /products?size=0  →  400  {"error": "size must be between 1 and 5"}
GET /debug/queries  →  200  {"queries": 5}

Your task: add MAX_PAGE_SIZE = 5. Read size with PAGE_SIZE as the default, and answer 400 when it is below 1 or above 5. Write the page query the starting code lost again, with LIMIT set to size, keep the answer in a variable, and cache each page under its own key for CACHE_SECONDS.


Assignment
Follow the Coding Tutorial to add a page size limit to GET /products and give each page its own cache entry.


Hint
Build the key from both after and size, with str(...) around the numbers. Check the size before you make the key, so a refused size never runs a query or fills a cache entry.


STEP 1 OF 10
    Ctrl + Enter to check

    Speed Project in Python

    Keep going with Python1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free