Marking Items Used
Food Tracker (FastAPI)
Chapter 8 · Marking Items Used
Every earlier chapter built toward this exact moment: an item is finally used up, and the row created back in Chapter 5 needs to reflect that — without ever disappearing from the history Chapter 7 searches.
The Route
expiry_date = None pays off Chapter 2's own nullable design — the row stays in the table forever, but its live expiry date genuinely goes away, exactly what Chapter 6's own expiry_date.isnot(None) filter already expects. The combined item_id == item_id, status == "active" filter means marking an already-used item "used" again matches no row at all — a safe no-op, not a re-stamped timestamp.
item_id: int isn't just documentation — declaring the path parameter's type means FastAPI validates and coerces it automatically, the same mechanism Chapter 5's own request-body validation used. A request to /api/items/abc/use is rejected with a 422 before mark_used's own body ever runs, since "abc" can't be parsed as an int — one more place this course's validation happens structurally, through a type annotation, rather than through a hand-written check.
GET — a browser's own link-prefetching or a crawler following every link on a page could trigger it without the user ever intending to. PATCH requires an explicit fetch call from real JavaScript, never something a browser might do on its own while simply loading a page.
Wiring It Into the Frontend
ItemsContext specifically because several separate React components each needed to react to the same mutation, with no direct relationship between them. This app has no component tree at all — markUsed can simply call loadAlerts() and loadRecipeSuggestions() directly, by name, because there are only ever a handful of views and no framework-imposed boundary between them. This isn't a missing feature; it's the direct, honest payoff of Chapter 1's own "deliberately minimal frontend" choice — a coordination problem only really needs a coordination mechanism once the app is complex enough to have one, and this one deliberately isn't.
Where This Course Is Headed
Recipe lookup with TheMealDB next — a second external API integration, reusing Chapter 3's own lessons.
Hands-On Exercises
Explain what the combined item_id == item_id, status == "active" filter actually prevents, and what would go wrong without the status == "active" part if a user managed to click "Mark Used" twice.
📄 View solutionExplain what happens to a request to /api/items/abc/use, and why this counts as the same kind of validation Chapter 5 covered for request bodies, just applied to a path parameter instead.
📄 View solutionExplain why this course never needed a coordination mechanism like Food Tracker (React + Express)'s own ItemsContext, tracing the reason back to a decision made in Chapter 1.
📄 View solutionChapter 8 Quick Reference
- Route: PATCH /{item_id}/use — sets status='used', used_at, clears expiry_date to None
- Guard: filtering on status == "active" too makes a duplicate click a safe no-op
- Path parameter validation: item_id: int is validated automatically, the same mechanism as Chapter 5's own body validation
- Never a GET: a state-changing action must require an explicit fetch call, not something a browser could trigger on its own
- No Context needed: markUsed calls loadAlerts()/loadRecipeSuggestions() directly — a direct payoff of this course's own deliberately minimal frontend
- Next chapter: Recipe Lookup with TheMealDB