Capstone: Choosing and Justifying a Framework for a Real Project

Web Framework Internals

Chapter 10 ยท Capstone: Choosing and Justifying a Framework for a Real Project

Nine chapters built real routers, real template engines, real ORMs, and real middleware chains from scratch, then checked how five real frameworks each answer the identical underlying questions. This capstone puts all of it to work on one real, concrete decision — not "which framework is best," a question this course has deliberately never tried to answer, but "which framework is best for this project," worked through criterion by criterion using nothing but findings this course already verified.

The Scenario

A four-person team at a mid-size logistics company, Meridian Freight, has six weeks to replace a spreadsheet-based shipment tracker with a real internal tool. The real requirements, gathered directly from the team:

#Requirement
1A genuinely relational data model — shipments, carriers, routes, customers — with reporting queries that regularly join across all four
2A separate mobile-app team (a different company) needs a real, stable, documented JSON API to build a warehouse-scanning app against, with minimal back-and-forth
3Internal staff view delivery notes containing rich text submitted by drivers through a separate intake form — this must never become an injection vector
4No dedicated DBA or DevOps role; the schema will genuinely change nearly every week as real requirements get clarified
5One team member has three real years of Django experience; the other three are generalists with no strong framework preference
6A hard six-week deadline for a working first version

Applying Chapters 2–3: Routing

Requirement 2 — a separate team needs a stable, documented API contract, with minimal back-and-forth — maps directly onto Chapter 3's own real, verified finding: FastAPI's item_id: int annotation does genuine double duty, driving both real request validation and the live, auto-generated /docs Swagger UI page from the identical source-code declaration. None of the other four routing systems Chapter 3 checked — Django, Express, Rails, Laravel — produce that documentation automatically from the route declaration itself. For a team with a genuinely separate, external consumer of the API who needs to work independently rather than asking questions in a shared chat channel, that's not a nice-to-have; it's the single clearest, most direct match between a real requirement and a real, previously-verified framework capability anywhere in this decision.

Applying Chapters 4–5: Templating

Requirement 3 — untrusted rich text, rendered on internal pages, must never become an injection vector — is precisely the real vulnerability Chapter 4 built and closed by hand, and Chapter 5 verified across seven real systems. Django's own quoted documentation states the strongest, most direct real guarantee of any system checked: "If you're using Django's template system, you're protected." Chapter 5 also verified a genuine, real second layer worth weighing for this specific requirement — Django's own documented refusal to "invent a programming language" inside its templates, contrasted directly against Jinja2's own real, quoted ability to call arbitrary functions with arguments from inside a template. For a field genuinely fed by outside submissions, a template language that's structurally incapable of executing arbitrary logic even if a future template were written carelessly is a real, concrete defense-in-depth property, not just a marketing point.

Applying Chapters 6–7: Data Access

Requirements 1 and 4 pull in genuinely opposite directions, and Chapter 7's own real findings name the exact tension directly. SQLAlchemy's own quoted Data Mapper design — keeping the mapped class "entirely separate" from persistence logic — is real, genuine strength for requirement 1's own complex, multi-table reporting joins, since nothing about the ORM's own design constrains how a query can be shaped. But Chapter 7 also verified, directly, that SQLAlchemy ships with zero built-in migration tooling at all — Alembic is a real, separate package, installed and configured independently. For requirement 4's own weekly schema churn, with no dedicated DBA to own a separate migration tool, that's a genuine, real cost. Django's own Active Record ORM, by contrast, ships migrations built directly in, tracked automatically — the exact opposite tradeoff, at the exact opposite requirement.

A real, honest compromise, not a forced choice
Django's own ORM doesn't forbid a genuinely complex, hand-written query when one is actually needed — it can drop into raw SQL for the small number of reports where that's the right tool. Given requirement 4's own real, weekly schema-change cadence and requirement 5's own lack of dedicated DevOps time, Django's built-in migrations are weighted more heavily here than SQLAlchemy's own genuine query-flexibility advantage — a real, reasoned tradeoff for this project's own specific balance of needs, not a general claim that Django's ORM is simply "better."

Applying Chapters 8–9: Middleware

Requirement 3's own security concern extends one layer further, into middleware. Chapter 9 verified Django's own real default MIDDLEWARE list ships CsrfViewMiddleware and SecurityMiddleware already correctly ordered, out of the box — per Chapter 9's own quoted finding, Django applies this list "top-down" for the request, with the security-relevant layers already placed where Django's own documentation recommends. For a four-person team with no dedicated security review process and a six-week deadline, a framework that ships a real, already-correctly-ordered default middleware stack removes an entire category of decision the team would otherwise have to get right themselves, under real time pressure.

The Real, Reasoned Decision

Every section above, except the routing section, points toward Django. Requirement 2 — the separate mobile team's own need for a documented API contract — is the one real requirement Django's own ecosystem, verified across this course's own five routing/data-access/middleware comparisons, simply doesn't answer as directly as FastAPI does. Forcing one single framework to be equally strong at both jobs would mean accepting a real, avoidable weakness somewhere in the system, for the sake of using only one framework.

Chapter 1's own real "micro vs. full-stack" framing — not a fixed property of a framework, but "a label for exactly how many of [the] four capabilities a given framework decides to ship as standard, versus leave as an explicit, deliberate integration point for something else" — applies just as well one level up, at the level of the whole system being built, not just one framework's own feature list. The real, reasoned decision: build the internal admin and reporting application in Django, leaning directly on its own verified migrations, secure-by-default templating, and correctly-ordered default middleware for a small team under real deadline pressure — and expose a small, separate FastAPI service, reading from the identical underlying database, specifically for the warehouse-scanner API. Neither framework is asked to do the one job the other is genuinely, verifiably better at.

Why Rails and Laravel were considered, and set aside
Rails' own real ActiveRecord schema-inference convenience (Chapter 7) and Laravel's own real, quoted historical "ActiveRecord implementation" framing plus Blade's own real compile-to-PHP performance (Chapter 5) are both genuine, verified strengths this course confirmed directly — but requirement 5 names no team member with real Ruby or PHP experience, a concrete, real cost against a hard six-week deadline that this project's own specific circumstances weigh more heavily than either framework's own genuine technical merits.

What Made This Decision, Chapter by Chapter

ChaptersReal, verified finding appliedRequirement it answered
1"Micro vs. full-stack" as a spectrum, not a fixed label — reapplied at the system levelJustifying two frameworks over one
2–3FastAPI's type hints driving both validation and real, auto-generated /docs#2 — a documented API for a separate team
4–5Django's quoted "you're protected" auto-escaping, plus its real "not a programming language" restriction#3 — untrusted rich text rendered safely
6–7SQLAlchemy's Data Mapper query flexibility vs. Django's real built-in migrations#1 and #4, weighed against each other directly
8–9Django's real, correctly-ordered default MIDDLEWARE list#3's own security dimension, and #6's time pressure

Course complete. Every real, verified finding across all nine prior chapters was reusable here, not as trivia, but as an actual decision-making tool — the entire real point of building each mechanism by hand before ever comparing five frameworks' own real answers to it.

Hands-On Exercises

Exercise 1

Meridian Freight's real requirement 5 changes: the team gains a fifth member with three real years of Ruby on Rails experience, and loses its one Django-experienced developer. Re-run this chapter's own Chapter 6-7 and Chapter 8-9 reasoning with Rails substituted for Django, and explain whether the final two-framework decision (Rails + FastAPI, in this revised scenario) would still make sense, or whether some other combination now reads better.

๐Ÿ“„ View solution
Exercise 2

This chapter's own decision explicitly weighs requirement 4 (weekly schema churn, no dedicated DevOps) more heavily than requirement 1 (complex reporting joins) when choosing Django's own built-in migrations over SQLAlchemy's own Data Mapper flexibility. Construct a genuinely different real scenario โ€” changing only requirements 1 and 4 โ€” where that specific weighting should flip, and explain why.

๐Ÿ“„ View solution
Exercise 3

This chapter's own final decision uses two separate frameworks reading from one shared database. Using Chapter 8's own real middleware concepts specifically, identify one genuine, concrete risk this split introduces that a single-framework system would not have to deal with at all, and explain what kind of check (in either the Django app or the FastAPI service) would need to exist to manage it.

๐Ÿ“„ View solution

Chapter 10 Quick Reference

  • The real question this capstone answers โ€” not "which framework is best," but "which framework is best for this project," using nothing but findings this course already verified
  • Routing (Ch.2-3) โ€” FastAPI's own verified type-hint/auto-docs finding directly answered a real, separate-team API-documentation requirement
  • Templating (Ch.4-5) โ€” Django's own quoted auto-escaping guarantee and its real "not a programming language" restriction directly answered a real untrusted-content requirement
  • Data access (Ch.6-7) โ€” SQLAlchemy's real query flexibility vs. Django's real built-in migrations, weighed directly against this specific project's own real constraints
  • Middleware (Ch.8-9) โ€” Django's own real, correctly-ordered default MIDDLEWARE list reduced real decision-making load under deadline pressure
  • The real, honest conclusion โ€” two frameworks, each used specifically where its own verified strength directly serves a real requirement, applying Chapter 1's own "micro vs. full-stack" framing at the level of a whole system
  • Course complete โ€” Web Framework Internals, 10/10 chapters