💻 Coding
Django 4.2 LTS to 5.2 LTS Upgrade Planner: Python 3.10+ Floor, Stepwise 5.0 and 5.1 Hops, python -Wa Deprecation Sweep, django-upgrade Codemods, STORAGES Setting, index_together and pytz Removals, and a Third Party Package Matrix
Plan a Django upgrade from 4.2 LTS to 5.2 LTS as a series of safe hops: environment floors, a deprecation sweep with warnings turned on, django-upgrade codemods, the removals that actually break 4.2 code, a package compatibility matrix, migration checks, and a deploy and rollback plan for each step.
0Reviews
Prompt
Act as a senior Django engineer who has moved several production apps from one LTS release to the next, upgrades one minor version at a time, and lets the deprecation warnings drive the work list. Inputs: - Current versions: Django, Python, database engine and version, OS image: [CurrentStack] - requirements or pyproject dependency list with pinned versions: [Dependencies] - Settings excerpts and code patterns you know you use (storage settings, timezone handling, custom auth, model Meta options, test helpers): [SettingsAndPatterns] - Test suite size, CI setup, and how long a full run takes: [TestSuite] - Deploy method and tolerance for downtime: [DeployContext] - Output format: [Format] Generate: 1. Floors table: Django 5.x needs Python 3.10 or newer, and each release raises database minimums (for PostgreSQL, 5.2 expects 14 or newer). Compare against CurrentStack and list what must move first. 2. Hop plan: 4.2 to 5.0, then 5.1, then 5.2, each its own branch and deploy. Never jump straight to 5.2. 3. Warning sweep for each hop: run the suite with python -Wa manage.py test (or PYTHONWARNINGS=always with pytest), collect RemovedInDjango warnings, and fix all of them before bumping the version. 4. Codemods: run django-upgrade with --target-version for the hop, and pyupgrade for the Python floor, then review the diff by hand. 5. Breaking removals mapped to SettingsAndPatterns, for example: DEFAULT_FILE_STORAGE and STATICFILES_STORAGE replaced by STORAGES, index_together replaced by Meta.indexes with a migration, pytz support and USE_DEPRECATED_PYTZ removed in favor of zoneinfo, USE_L10N removed, logout over GET removed, assertQuerysetEqual renamed to assertQuerySetEqual, CheckConstraint check renamed to condition. For each: file, fix, test. 6. Package matrix from Dependencies: package, current pin, first version that supports the target Django, blocker yes or no, and an alternative if abandoned. 7. Migration safety: makemigrations --check after each hop, review any generated migration, and run migrations against a production sized copy. 8. Deploy and rollback for each hop from DeployContext, including what to watch in logs for the first day. 9. Mark anything you cannot confirm from the official release notes as "check the 5.x release notes". Constraints: - Ordered, checkable steps. Show commands exactly. No em dashes.
Instructions
Replace every [bracket] with your details before running. Works on ChatGPT, Claude, and Gemini.
Generated Output
This image was generated using the prompt above.

Examples
Example Input
CurrentStack: Django 4.2.16, Python 3.9, PostgreSQL 13 on RDS, Debian bullseye container Dependencies: djangorestframework 3.14, django-storages 1.13, celery 5.3, django-filter 23.2, django-celery-beat 2.5, django-two-factor-auth 1.15 SettingsAndPatterns: DEFAULT_FILE_STORAGE points at S3 storage; two models use index_together; one management command uses pytz; tests use assertQuerysetEqual TestSuite: 1,900 tests, GitHub Actions, about 11 minutes DeployContext: ECS rolling deploy, no maintenance window Format: floors, hop plan, fixes table, package matrix, deploy notes
Example Output
1) FLOORS
| Item | Now | Needed for 5.2 | Action |
| Python | 3.9 | 3.10+ | Move to 3.12 first, on Django 4.2 |
| PostgreSQL | 13 | 14+ | Upgrade RDS to 16 before the 5.2 hop |
| Base image | bullseye | any with Python 3.12 | Switch to python:3.12-slim-bookworm |
Ship Python 3.12 on 4.2 alone and watch it for a week.
2) HOP PLAN
Branch upgrade/5.0, then upgrade/5.1, then upgrade/5.2. One deploy per hop.
3) WARNING SWEEP (repeat every hop)
python -Wa manage.py test 2>&1 | grep -o 'RemovedInDjango[0-9]*Warning.*' | sort | uniq -c
Fix until the list is empty, then bump Django.
4) CODEMODS
pip install django-upgrade pyupgrade
git ls-files -z -- '*.py' | xargs -0 django-upgrade --target-version 5.0
git ls-files -z -- '*.py' | xargs -0 pyupgrade --py310-plus
Review the diff before committing.
5) FIXES
| Pattern | Fix | Test |
| DEFAULT_FILE_STORAGE = S3 storage | STORAGES = {"default": {"BACKEND": "storages.backends.s3.S3Storage"}, "staticfiles": {...}} | upload test on staging bucket |
| index_together on Invoice, Shipment | Meta.indexes = [models.Index(fields=[...])], makemigrations; the migration renames, it should not rebuild | inspect sqlmigrate output |
| pytz in import_rates command | zoneinfo.ZoneInfo("America/Chicago") | command test with a DST date |
| assertQuerysetEqual | assertQuerySetEqual | suite passes |
6) PACKAGE MATRIX
| Package | Pin | Target | Blocker |
| djangorestframework | 3.14 | 3.15+ for 5.x | bump on the 5.0 hop |
| django-storages | 1.13 | 1.14+ (STORAGES support) | bump before the storage change |
| django-filter | 23.2 | 24.x | bump |
| django-celery-beat | 2.5 | check release notes for 5.2 | possible blocker |
| django-two-factor-auth | 1.15 | 1.16+ | check release notes |
| celery | 5.3 | 5.4 | not tied to Django |
7) MIGRATIONS
python manage.py makemigrations --check --dry-run after each hop. Run migrate on a snapshot restored from production before deploying.
8) DEPLOY
ECS rolling deploy is fine because the index migration is a rename. Watch Sentry for DeprecationWarning noise, 500s on file upload, and Celery beat schedule errors for 24 hours. Rollback: redeploy the previous image; the rename migration is reversible.
9) CHECK
Exact minimum versions for django-celery-beat and django-two-factor-auth: check their changelogs and the 5.2 release notes.