Premier League Predictor: Django & MySQL — Chapter 4, Exercise 3 ==================================================== TASK Build the full click-to-pair page yourself against a real gameweek, enter at least 3 fixtures, then deliberately remove the X-CSRFToken header from addFixture() and confirm the real, different error you get back compared to attempting to reuse an already-fixtured team. SOLUTION Steps to complete this exercise: 1. Wire up the URL routes for fixture_entry and create_fixture, save fixture_entry.html and fixtures.js as shown in this chapter, and confirm a real gameweek with a real season already has 20 SeasonTeam rows (from earlier chapters). 2. Load the fixture-entry page for that gameweek and confirm the 20 team buttons appear immediately on page load, with no visible loading delay — direct evidence of Exercise 1's own server-side rendering claim. 3. Click three real team pairs into Home/Away and press Add Fixture each time, confirming each pair's own buttons become disabled and the slots reset — three genuine fixtures now stored. 4. In addFixture(), comment out or delete the 'X-CSRFToken': csrftoken, line entirely, then reload the page (a fresh page load re-triggers @ensure_csrf_cookie, so the cookie is still present in the browser even though the header is no longer being sent). 5. Attempt to add a fourth, genuinely new fixture (two teams not yet used). The fetch call should return a real 403 Forbidden response, and the page's own error handling (reading error.error from the JSON body) will likely fail or show something unexpected, since a 403 CSRF rejection from Django's middleware doesn't return the same {"error": "..."} JSON shape create_fixture itself returns for a genuine business-logic failure — worth inspecting directly in the browser's network tab to see the real raw response. 6. Restore the X-CSRFToken header, then attempt to submit a fixture reusing one of the three already-used teams from step 3. This time the request passes CSRF validation successfully and reaches create_fixture's own code, which returns a real 409 Conflict with the JSON body {"error": "One of these teams is already fixtured this gameweek"} — correctly displayed via the page's own alert(). One-sentence confirmation: removing the CSRF header produces a real 403 rejected before create_fixture's own logic ever runs, while reusing an already-fixtured team (with the header restored) produces a real 409 from inside create_fixture's own deliberate duplicate check — two genuinely different failures at two genuinely different layers. WHY THIS WORKS AS AN ANSWER ---------------------------- It walks through building and using the real page end to end, then deliberately reproduces both failure modes named in Exercise 2 (the 403 CSRF rejection and the 409 duplicate-team rejection) and confirms, by actually running both, that they are genuinely different responses happening at genuinely different points in the request's own lifecycle.