Project Overview & Django + MySQL Setup
Premier League Predictor: Django & MySQL
Chapter 1 · Project Overview & Django + MySQL Setup
This is the second of four courses building the exact same Premier League prediction tracker in four genuinely different architectures — Premier League Predictor (FastAPI & PostgreSQL, complete — see plpredict-fastapi1), Premier League Predictor (FastAPI & Redis), and Premier League Predictor (Astro) are its siblings, the latter two still outlined rather than generated yet. Where the FastAPI variant leaned into a real, typed API layer, this course leans into Django's own ready-made admin interface — a genuine fit for a project with this much real, recurring manual data entry.
What the App Actually Does
The shared spec every course in this set builds toward — a personal, weekly Premier League prediction tracker:
- Track every fixture across a real 38-gameweek Premier League season, 20 teams, 10 fixtures per gameweek.
- Record four real prediction sources per fixture: the user's own prediction, the BBC's expert prediction (currently Chris Sutton), that week's guest predictor(s) — genuinely variable, with multiple guests averaged into a single figure for the week — and the BBC's own published AI-generated prediction, manually transcribed rather than scraped or generated by this app.
- Score two different things per prediction once a result is in — a correct score (the exact scoreline matched) and a correct result (the predicted win/draw/loss outcome matched, even if the scoreline itself didn't).
- Maintain the real league table — points, goal difference, wins/draws/losses — alongside a second, parallel prediction league table ranking how each of the four real predictors is actually doing across the season.
- Handle promotion and relegation between seasons — the bottom three teams auto-calculated and removed at season end; the three promoted teams entered manually.
plpredict-fastapi1's own Chapter 6 resolved this directly with the user: 40 points for a correct score, 10 points for a correct result. This course reuses that same confirmed split rather than asking again — a real product decision, made once, that applies to every variant in this set.
Why Django + MySQL for This One
This project has a genuinely heavy, recurring manual-entry burden — 10 fixtures every gameweek, up to 5 real predictions per fixture, a real result entered for every fixture, three promoted teams typed in by name every season. That's exactly the shape of work Django's own admin interface exists to make fast: generated automatically from the models this course defines, with zero hand-built forms needed for the raw data-entry side of the job (Chapter 3). MySQL is the natural, familiar real-world pairing for a Django project — a genuinely different relational engine from the FastAPI variant's own PostgreSQL, letting the two reference implementations be read side by side later.
CREATE UNIQUE INDEX ... WHERE source != 'guest') — to allow multiple guest predictions per fixture while still enforcing exactly one user/expert/AI prediction each. MySQL has no equivalent mechanism — it doesn't support a WHERE clause on an index at all. This course will need a genuinely different real solution to the identical problem when Chapter 5 gets there — flagged honestly now, not silently discovered later.
Setting Up: Django & MySQL
A local Python install with pip, and a working local MySQL server, are assumed from here on. Creating the database first, with an explicit modern charset:
utf8mb4, not plain utf8 — MySQL's own historical utf8 charset is actually a restricted 3-byte encoding that can't store every real Unicode character (emoji included); utf8mb4 is the genuinely full implementation, and the standard real-world choice for a new MySQL database today.
mysqlclient is a genuine C extension wrapping MySQL's own native client library — fast, but it needs real system build dependencies (libmysqlclient-dev on Debian/Ubuntu, Microsoft's C++ Build Tools on Windows) to install at all, unlike PostgreSQL's own psycopg2-binary, which ships pre-compiled. If that friction genuinely gets in the way during development, pip install PyMySQL plus two lines at the very top of manage.py — import pymysql; pymysql.install_as_MySQLdb() — makes Django use a pure-Python MySQL driver instead, with no compiled extension required at all. The real tradeoff: PyMySQL is genuinely slower under heavy load than mysqlclient, a real cost worth knowing about before choosing it for anything beyond local development.
Starting the Django Project
Pointing the new project at the real MySQL database in pl_predictor_site/settings.py:
Add 'predictor' to INSTALLED_APPS, then confirm the connection works by running Django's own initial migrations against the real database:
'charset': 'utf8mb4' inside OPTIONS makes Django's own connection use the same full-Unicode charset the database was created with — a mismatch between the two (a utf8mb4 database with a connection defaulting to plain utf8) is a real, documented source of silent data corruption for anything outside the restricted 3-byte range, not just a cosmetic setting.
Where This Course Is Headed
A real Django-model schema for teams, seasons, gameweeks, and fixtures (Chapter 2); the Django admin as the real manual-entry tool for teams and fixtures (Chapter 3); the fast click-to-pair fixture-entry UI built outside the admin (Chapter 4); recording all four prediction sources, and a genuinely MySQL-specific answer to the partial-unique-index gap flagged above (Chapter 5); entering results and calculating the confirmed 40/10 scoring (Chapter 6); the real league table (Chapter 7); the prediction league table (Chapter 8); promotion and relegation (Chapter 9); styling and the gameweek/season selector (Chapter 10); deployment (Chapter 11); and a capstone integrating this predictor into the existing Astro-based site (Chapter 12).
Hands-On Exercises
Explain why this course reuses the 40/10 point values confirmed in plpredict-fastapi1's own Chapter 6 rather than asking the question fresh, and what that implies for any future variant in this same set.
📄 View solutionExplain why utf8mb4 is the correct charset choice for the pl_predictor database instead of plain utf8, and why the OPTIONS charset setting in DATABASES needs to match it.
📄 View solutionSet up the pl_predictor MySQL database and a working Django project connected to it yourself (using either mysqlclient or the PyMySQL alternative), confirm python manage.py migrate runs successfully, and write one sentence explaining what that command actually confirmed.
📄 View solutionChapter 1 Quick Reference
- The shared app — a weekly Premier League prediction tracker: 4 real prediction sources per fixture, scored 40/10/0, across a real 38-gameweek season
- Real point values (confirmed) — 40 for a correct score, 10 for a correct result, reused directly from plpredict-fastapi1's own Chapter 6
- Why this variant — Django's own ready-made admin as a fast tool for this project's genuinely heavy manual-entry workload, paired with MySQL
- Flagged early — MySQL has no equivalent to PostgreSQL's partial unique index; Chapter 5 will need a genuinely different real fix for the same guest-prediction problem
- Database — MySQL, created as
pl_predictorwith explicitutf8mb4charset - Driver choice —
mysqlclient(fast, needs real build tools) orPyMySQL(pure Python, easier install, slower under load) - Next chapter: Data Modeling — teams, seasons, gameweeks & fixtures as Django models