Premier League Predictor: Django & MySQL — Chapter 9, Exercise 2 ==================================================== TASK Explain why this chapter deliberately splits promotion/relegation into a programmatic rollover_survivors view plus Chapter 3's own SeasonTeamInline, rather than building one combined route that also accepts the 3 promoted teams' names the way the FastAPI/PostgreSQL sibling course does — and why that split is a genuinely good fit for Django specifically. SOLUTION The two halves of a real rollover are genuinely different kinds of work. Carrying the 17 survivors forward is purely mechanical: given a correctly-ordered league table, "everyone except the bottom three" is a deterministic fact with no human judgment involved at all — a computer can and should just do it. Which 3 teams get promoted, by contrast, isn't derivable from anything already in this app's own database at all; it's a genuine real-world fact (the result of the Championship's own promotion playoffs) that has to be typed in by a person, no matter which framework is used. The FastAPI/PostgreSQL sibling handles both halves in one route because it has to build its own promoted-team-entry mechanism from scratch either way — FastAPI has no equivalent to a built-in admin interface, so writing one small combined endpoint that accepts three team names alongside the survivor rollover is the natural, minimal amount of new code for that stack. Django is different specifically because Chapter 3 already built a real, working "add or remove a team from a season" tool — SeasonTeamInline — entirely for free, as a side effect of registering SeasonAdmin. That tool already handles exactly the promoted-team-entry problem: picking an existing team via autocomplete, or creating a brand-new one via the "+" popup, both inside the ordinary Season admin page, with the existing max_num=20/validate_max=True cap already preventing the season from exceeding 20 teams. Building a second, parallel API route that duplicates this — accepting team names in a JSON body, deciding whether to create a new Team or reuse an existing one, re-implementing the 20-team cap — would mean writing real new code to recreate something that already exists and already works, purely to match the other course's own shape. Splitting the work this way lets each half be handled by the tool best suited to it: real application code for the deterministic, mechanical part (rollover_survivors), and Django's own admin — genuinely built for exactly this kind of "a human needs to make a small number of free-form edits to structured data" task — for the part that requires a person's own judgment. WHY THIS WORKS AS AN ANSWER ---------------------------- It identifies the real underlying difference between the two halves of the task (mechanical vs. requiring human judgment), explains specifically why FastAPI's own lack of a built-in admin makes one combined route the natural choice there, and explains why Django's already-existing SeasonTeamInline (built in Chapter 3, not invented for this exercise) makes rebuilding the same functionality as a second API route a genuine, avoidable duplication of already-working code.