Update Django to 5.2 - #3768
Open
mbertrand wants to merge 7 commits into
Open
Conversation
OpenAPI ChangesNo changes detected Unexpected changes? Ensure your branch is up-to-date with |
1 task
mbertrand
force-pushed
the
mb/django-5-upgrade
branch
from
August 13, 2026 14:14
41bf855 to
9d79dda
Compare
mbertrand
marked this pull request as ready for review
August 13, 2026 15:23
Contributor
There was a problem hiding this comment.
Pull request overview
Upgrades the Django backend to 5.2.16 and updates related dependencies and compatibility code.
Changes:
- Updates Django, django-filter, DRF, PostgreSQL CI, and Renovate constraints.
- Adapts APISIX middleware and settings for Django 5.2.
- Migrates the deprecated channel index configuration.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Locks upgraded dependencies. |
renovate.json |
Allows Django 5.x updates. |
pyproject.toml |
Updates dependency constraints. |
main/settings.py |
Removes obsolete localization setting. |
main/middleware/apisix_user.py |
Adapts middleware response handling. |
main/middleware/apisix_user_test.py |
Updates middleware invocation coverage. |
fixtures/common.py |
Suppresses an upstream deprecation warning. |
channels/models.py |
Replaces deprecated index configuration. |
channels/migrations/0017_channelgrouprole_index.py |
Renames the existing database index. |
.github/workflows/ci.yml |
Upgrades CI PostgreSQL to version 16. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (1)
fixtures/common.py:59
- Scope this suppression to django-safedelete. Because the filter currently matches only the warning text, any future first-party call to
LogEntryManager.log_action()will also be silently ignored, defeating this fixture's warnings-as-errors check. Django emits this warning withstacklevel=2, so the reported module for the known third-party call issafedelete.admin.
warnings.filterwarnings(
"ignore",
message=r"LogEntryManager\.log_action\(\) is deprecated.*",
category=DeprecationWarning,
)
Django 5 gives RemoteUserMiddleware its own __call__ that discards the return value of process_request, so ApisixUserMiddleware returning self.get_response(request) made every request run its downstream chain twice — doubled writes, doubled side effects, throttle limits consumed at 2x. Returning None and letting __call__ drive the chain fixes it, and behaves identically on 4.2. Same fix as learn-ai 2fe143b. The rest: - index_together was removed in 5.1; Meta.indexes replaces it and the migration renames the existing index in place rather than rebuilding it - USE_L10N was removed in 5.0 - django-filter 2.4.0 calls ChoiceField._set_choices, which 5.0 removed. The >=2.4.0,<3 pin could never reach a fixed release because upstream switched to CalVer (21.1 ... 26.1), so the upper bound comes off - djangorestframework 3.17.2 fixes RawPostDataException when DRF reads request.data under 5.2 - django-safedelete 1.4.1 still calls the deprecated log_action(); ignore the warning until upstream moves to log_actions() - renovate was capped at Django <5, which is why 4.2 sat here through its EOL; raise it to <6 so 5.2.x patches come through Full suite passes apart from the ordering flakes tracked in mitodl/hq#12841. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Django 5.2 requires PostgreSQL 14+. CI was still on 12.22; local dev already runs 16 via docker-compose.services.yml. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Matches taskbatch_job_status_idx and content_fb_course_time_idx rather than Django's auto-generated hash name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The same_user case called process_request() directly, so it couldn't catch the duplicate get_response() run this branch fixes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mbertrand
force-pushed
the
mb/django-5-upgrade
branch
from
August 13, 2026 16:50
9605cdf to
c2967d7
Compare
Matching on message alone would also swallow the warning for any first-party log_action() call. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What are the relevant tickets?
Replaces #3742.
Description (What does it do?)
Updates Django 4.2.30 to 5.2.16. and makes other changes required to fix the failing unit tests in #3742
The biggest change worth a close look is in
ApisixUserMiddleware. Django 5 givesRemoteUserMiddlewareits own__call__that ignores whateverprocess_requestreturns, so ourreturn self.get_response(request)meant every request ran the rest of the middleware chain and the view a second time. ReturningNonefixes it and behaves the same on 4.2. Same fix I made in learn-ai (https://github.com/mitodl/learn-ai#423).The rest:
index_togetherwas removed in 5.1, soChannelGroupRoleusesMeta.indexes. The migration renames the existing index instead of rebuilding it.USE_L10Nwas removed in 5.0.>=2.4.0,<3, which resolves to 2.4.0 from 2020. It callsChoiceField._set_choices, which Django 5.0 removed — 138 test failures on its own. The pin could never have reached a fix because django-filter moved to CalVer (21.1 through 26.1), so the upper bound is gone and uv.lock is the pin.RawPostDataExceptionwhen DRF readsrequest.data.log_action(), so that warning is ignored until upstream switches tolog_actions().<5, which is why we stayed on 4.2 through its EOL. Raised to<6so 5.2.x patches come through without 6.x landing on its own.How can this be tested?
docker compose build --no-cache web celeryUnit tests should all pass.