Premier League Predictor: Django & MySQL — Chapter 3, Exercise 3 ==================================================== TASK Register the admin classes from this chapter, create a superuser (python manage.py createsuperuser), open a real Season in the admin, add teams via the SeasonTeamInline until you reach the 20-team cap, and confirm attempting to add a 21st is genuinely rejected on save, not just visually limited. SOLUTION Steps to complete this exercise: 1. Save admin.py exactly as shown in this chapter, with TeamAdmin, SeasonTeamInline (including max_num = 20 and validate_max = True), and SeasonAdmin. 2. Create a superuser: python manage.py createsuperuser 3. Start the server (python manage.py runserver) and log into /admin/. 4. Create a new Season (or open an existing one with fewer than 20 SeasonTeam rows). 5. Using the SeasonTeamInline on the Season's own edit page, add teams one at a time via the team autocomplete field, saving as needed, until the season has exactly 20 SeasonTeam rows. At that point, no further blank row should be offered for adding a 21st — confirming max_num's own real display behavior. 6. To genuinely test enforcement rather than just the display limit, attempt to bypass it: with 20 rows already present, use the browser's own developer tools to duplicate one of the existing inline form's HTML (adjusting its own hidden index/ID fields to look like a new, 21st form) and submit the page with a 21st team filled in. 7. Confirm the save is genuinely rejected with a real validation error from Django (a message indicating too many forms were submitted), not silently accepted — proving validate_max = True is doing real enforcement work, independent of whatever the normally-rendered page happened to display. One-sentence confirmation: with validate_max = True in place, a submission engineered to include a 21st SeasonTeam form is rejected by Django's own formset validation, confirming the 20-team cap is a real, enforced rule and not merely a consequence of the admin page simply not offering a 21st blank row to fill in under normal use. WHY THIS WORKS AS AN ANSWER ---------------------------- It walks through the normal path to reaching the visible 20-team limit first, then deliberately goes further and constructs a real test that bypasses the normal UI to confirm actual server-side enforcement — directly testing the distinction Exercise 2 explained, rather than just observing that the admin page stops offering a blank row.