Django 4.2 Is Past End of Life: The 5.2 LTS Upgrade
Django 4.2 lost security support on 7 April 2026. On 4 August the security team patched four issues in 5.2 and 6.0 and nothing older, so the gap stopped being hypothetical. 5.2 LTS is the target, and the Python floor is where the time goes.
Django 4.2’s extended support ended on 7 April 2026. The download page still lists it, in the unsupported table, frozen at 4.2.30.
For four months after that date nothing happened. No CVE, no advisory, no reason for anyone to move. “Unpatched” stayed a line on a scanner report rather than something you could point at.
Then on 4 August the security team shipped 6.0.8 and 5.2.17, fixing four issues. The patches went to main, 6.1, 6.0, and 5.2. That is the entire list. There was no 4.2.31, and there will not be one.
| CVE | Severity | What it touches |
|---|---|---|
| CVE-2026-15307 | High | Spatial lookups accepting str and dict values into GDALRaster |
| CVE-2026-15830 | Moderate | Geometry collections |
| CVE-2026-15920 | Moderate | Admin URLField display |
| CVE-2026-15337 | Low | Translation utility |
Two of the four are GeoDjango. If you have never imported django.contrib.gis, those are somebody else’s problem. The admin URLField one is not: a URLField rendered in the admin is about as close to a default as this framework has.
Django’s advisories describe the branches that got fixes and say nothing about the ones that did not. That silence is the actual change at end of life. Whether a given CVE reaches the code you are running is now your question to answer, every time, with the patch diff open in another tab. Triage moved to your desk in April. This is just the first month it had anything in it.
The target is 5.2, and it is not 6.1
Django 6.1 came out on 5 August 2026, the day after that security release. It is the newest version and it has the shortest remaining window of anything supported.
| Version | Released | Security support ends | LTS |
|---|---|---|---|
| 4.2 | Apr 2023 | 7 Apr 2026 (over) | Yes |
| 5.0 | Dec 2023 | 2 Apr 2025 (over) | No |
| 5.1 | Aug 2024 | 3 Dec 2025 (over) | No |
| 5.2 | Apr 2025 | Apr 2028 | Yes |
| 6.0 | Dec 2025 | Apr 2027 | No |
| 6.1 | Aug 2026 | Dec 2027 | No |
| 6.2 | Apr 2027 (planned) | Apr 2030 | Yes |
5.0 and 5.1 are also dead, so there is no stepping stone worth stopping on. You install 5.2 and absorb three releases of changes at once.
Going to 6.1 instead buys you four fewer months than 5.2 and costs you a Python upgrade you may not be ready for. The next LTS is 6.2 in April 2027. Land on 5.2 now and your following jump is 5.2 to 6.2, sometime before April 2028, against an LTS that will have been out for a year by then. That is the path the release schedule is built for.
The Python floor is where the time goes
Django 5.2 supports Python 3.10 through 3.14, with 3.14 added in 5.2.8. The 5.2 release notes also say the 5.2.x series is the last to support 3.10 and 3.11. Django 6.0 and 6.1 require 3.12 or newer.
Which sets up a trap worth naming: Python 3.10 satisfies Django 5.2 and reaches its own end of life in October 2026. Upgrade the framework, clear the Django finding, and the same scanner opens a Python finding eight weeks later. If you are moving the runtime at all, move it to 3.12 or 3.13. That also leaves the door to 6.x open instead of requiring a second runtime bump to walk through it.
If the app is still on 3.9, which went end of life in October 2025, you have two unpatched layers stacked and an auditor counts them separately.
What actually breaks
The changes most likely to stall you are not in your code.
Django 5.2 dropped PostgreSQL 13, so you need 14 or higher. MySQL’s default charset moved from utf8mb3 to utf8mb4. The minimum oracledb went from 1.3.2 to 2.3.0, GDAL 3.0 and PostGIS 3.0 support is gone, and gettext needs 0.19. If your database is a managed instance sitting one major version too low, that upgrade has its own maintenance window and its own approval, and it is the long pole, not the pip install.
In application code, the ones that bite quietly: assigning directly to EmailMultiAlternatives.alternatives no longer works and you call attach_alternative() instead; the built-in aggregates (Avg, Count, Max, Min, StdDev, Sum, Variance) now raise TypeError when given the wrong number of arguments rather than doing something surprising; UniqueConstraint always honors violation_error_code and violation_error_message when they are set; HttpRequest.accepted_types comes back sorted by client preference; and the debug() context processor is no longer in the default project template.
Before any of that, get the free information. Run the suite you already have, on the Django you already run:
python -W error::DeprecationWarning manage.py test
Everything that surfaces is a thing 5.2 removed or is about to, and you learn it while the version pins are still untouched and every failure is unambiguous.
Your dependencies are dropping 4.2 faster than you are
Django REST Framework 3.18.0, released 7 August 2026, dropped Django 4.2, 5.0, and 5.1 in one commit and added 6.1. Wagtail 7.4 LTS lists Django 5.2 and 6.0, nothing older.
Staying on 4.2 pins everything that talks to it. The next DRF security fix will ship for a Django you do not run, and back-porting it becomes your job too. Check the support matrix of every package that reaches into Django internals before you commit to a date: admin customizations, custom auth backends, ORM extensions, and any CMS layer. “Django 5.2 supports it” and “your exact set of pins supports it” are different questions, and the gap between them is where upgrade estimates go wrong.
Then do the work in an order that keeps failures attributable. Deprecation pass on 4.2 first. Bump Django alone with every other pin held still, and run the suite. Bump the dependency tree after, one meaningful package at a time. Roll out to a slice of traffic before all of it, especially if the app leans on sessions, auth, or caching, where behavior changes tend not to show up as test failures.
Buying the bridge
HeroDevs and TuxCare both sell backported security patches for 4.2. That is a real option in two situations: the audit clock is shorter than the upgrade clock, or the app already has a decommission date and spending three weeks on a version bump is spending it on something that will be deleted.
For anyone else it is a bridge, and a bridge needs a date on the far end. Without one it quietly becomes the plan, and you buy it again next year.
The hour worth spending first is not the upgrade. It is the inventory: which Python minor you are on, which major version your database is on, and which of your pinned packages reach into Django internals. Those three answers are the difference between a week and a quarter, and you can get all three before lunch. The next security release will patch 5.2 and 6.x on whatever day it lands, and you already know which side of that line you are on.