Search nomadLab

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.

Updated

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.

CVESeverityWhat it touches
CVE-2026-15307HighSpatial lookups accepting str and dict values into GDALRaster
CVE-2026-15830ModerateGeometry collections
CVE-2026-15920ModerateAdmin URLField display
CVE-2026-15337LowTranslation 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.

Django security support windows. 4.2 LTS ran from April 2023 to April 2026 and is over. 5.2 LTS runs to April 2028. The non-LTS releases 6.0 and 6.1 end in April 2027 and December 2027, both sooner than 5.2. The next LTS, 6.2, arrives April 2027 and runs to April 2030. The newest release is not the one supported longest today 4.2 LTS ended Apr 2026 5.2 LTS to Apr 2028 6.0 to Apr 2027 6.1 to Dec 2027 6.2 LTS to Apr 2030 Apr 2023 Apr 2030
Support windows from the Django download page and release notes, checked 22 August 2026. 6.2 is roadmap, not released.

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.

VersionReleasedSecurity support endsLTS
4.2Apr 20237 Apr 2026 (over)Yes
5.0Dec 20232 Apr 2025 (over)No
5.1Aug 20243 Dec 2025 (over)No
5.2Apr 2025Apr 2028Yes
6.0Dec 2025Apr 2027No
6.1Aug 2026Dec 2027No
6.2Apr 2027 (planned)Apr 2030Yes

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.

Keep reading