Recipe Lookup with TheMealDB
Food Tracker (Django)
Chapter 10 · Recipe Lookup with TheMealDB
This chapter delivers the last named feature from Chapter 1's original spec, reusing the same integration pattern Chapter 4 already established — and running into a real, honest limitation specific to how this course's views are built.
The Same Limitation, Regardless of Framework
TheMealDB's filter-by-ingredient endpoint searches exactly one ingredient per request — this isn't a Django, FastAPI, or Firebase-specific constraint at all, it's simply a property of the external API itself, identical across all four Food Tracker courses. Every one of them has to fan out one request per expiring ingredient and merge the results afterward.
A View That Fans Out
A Real Cost of This Sequential Loop
Each requests.get() call here runs one after another, and this ordinary Django view blocks entirely until every single one finishes — five expiring ingredients means roughly five times the wait of firing them all at once. This is a genuine, honest cost specific to how this view is written: Food Tracker (FastAPI)'s own async patterns and Food Tracker (React + Firebase)'s Promise.all() both fire every ingredient lookup concurrently instead. Django does support async views (async def, since Django 3.1), but doing this properly would also require swapping the synchronous requests library for an async-compatible HTTP client — real additional complexity genuinely beyond this chapter's own scope, named honestly rather than glossed over.
Relevance Sorting — The One Place All Four Courses Converge
Sorting by len(matched_ingredients) descending surfaces recipes using the most expiring items first — directly serving Chapter 1's original point: using up as much soon-to-expire food as possible in one meal. This particular piece of logic is functionally identical across all four Food Tracker courses, each expressed in its own language's idioms — a genuine convergence point after several chapters of real, honest divergence.
Caching, Same Reasoning, a New Kind of Column
JSONField (native since Django 3.1, backed by real JSON column support in modern PostgreSQL, MySQL, and SQLite) is a genuinely interesting nuance worth naming directly: even a relational, schema-on-write framework has its own escape hatch for storing semi-structured, document-like data in a single column, when that's honestly the better fit — a list of matched-meal dictionaries here doesn't cleanly decompose into further normalized tables for this app's own modest needs. Relational and document approaches aren't a strict either/or; a real relational database can hold document-shaped data exactly where that's the more sensible choice.
JSONField is worth knowing about generallyWhere This Course Is Headed
Django REST Framework, deployment, and a capstone.
Hands-On Exercises
Explain why this view takes roughly N times as long as necessary for N expiring ingredients, and what the FastAPI and Firebase sibling courses do differently to avoid this specific cost.
📄 View solutionExplain how the matched_ingredients sort serves Chapter 1's original recipe-lookup intent, and why this chapter calls this one piece of logic essentially identical across all four Food Tracker courses.
📄 View solutionExplain what JSONField is, and why using it for RecipeCache doesn't actually contradict Django's own relational, schema-on-write identity.
📄 View solutionChapter 10 Quick Reference
- One ingredient per request — TheMealDB's own limitation, identical across all four courses
- Sequential, blocking loop — a real, honest cost; FastAPI's async and Firebase's
Promise.all()both avoid it by running concurrently matched_ingredientssort — the one piece of logic functionally identical across the whole quartetJSONField— Django's own escape hatch for document-shaped data inside a relational schema- Next chapter: Django REST Framework: Exposing an API Layer