Premier League Predictor: Django & MySQL — Chapter 5, Exercise 3 ==================================================== TASK Record a user, an expert, an AI, and two separately-named guest predictions against a single real fixture using upsert_prediction, then submit a second user prediction for the same fixture and confirm it updates the existing row (created: false) rather than creating a duplicate. SOLUTION Steps to complete this exercise: 1. Pick a real fixture (from an earlier gameweek entered via Chapter 4's own fixture-entry UI) and note its id. 2. POST five separate upsert requests to /fixtures//predictions/upsert/, each with a real, valid JSON body: {"source": "user", "predicted_home_score": 2, "predicted_away_score": 1} {"source": "expert", "predicted_home_score": 1, "predicted_away_score": 1} {"source": "ai", "predicted_home_score": 2, "predicted_away_score": 0} {"source": "guest", "guest_name": "Dave", "predicted_home_score": 3, "predicted_away_score": 2} {"source": "guest", "guest_name": "Priya", "predicted_home_score": 1, "predicted_away_score": 0} Each response should return {"id": , "created": true}, and GET /fixtures//predictions/ should now list exactly 5 rows. 3. POST a sixth request, reusing source: "user" against the same fixture with a different scoreline: {"source": "user", "predicted_home_score": 3, "predicted_away_score": 1} The response is {"id": , "created": false} — the same primary key as before, confirming update_or_create() found the existing user/fixture row via its lookup (fixture + source, with no guest_name since is_guest is False) and updated its predicted_home_score/predicted_away_score in place rather than inserting a new row. 4. Re-fetch GET /fixtures//predictions/ and confirm the list still contains exactly 5 rows total (not 6) — the user row's own predicted_home_score now reads 3, and the two guest rows (Dave and Priya) remain completely untouched, since their own lookup dict included guest_name and so never matched the user's own upsert. One-sentence confirmation: five distinct rows exist after step 2, step 3's second user upsert reuses the exact same row id and reports created: false, and the final row count stays at 5 — real, direct proof that update_or_create() is correctly finding and updating an existing prediction rather than ever inserting a genuine duplicate. WHY THIS WORKS AS AN ANSWER ---------------------------- It exercises all four real prediction sources including two independently-named guests, then specifically re-submits an already- recorded source to confirm the created: false / same-id / unchanged- row-count behavior update_or_create() is supposed to produce, verified by actually running the requests rather than only reasoning about them.