Avoid crawling the entire model graph when viewing RefreshTokenAdmin#1675
Merged
dopry merged 2 commits intodjango-oauth:masterfrom Apr 1, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses Django admin changelist performance and stability for RefreshTokenAdmin by preventing Django from performing an unbounded select_related() traversal on highly connected model graphs (Fixes #1674).
Changes:
- Set
RefreshTokenAdmin.list_select_relatedto("application", "user")to bound JOIN traversal. - Add a regression test asserting the changelist queryset’s
select_relatedstate is scoped (dict) rather than unbounded (True). - Document the fix in
CHANGELOG.mdand add the contributor toAUTHORS.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
oauth2_provider/admin.py |
Adds bounded list_select_related to RefreshTokenAdmin to avoid runaway JOIN recursion. |
tests/test_settings.py |
Adds regression test verifying select_related is bounded for RefreshTokenAdmin queryset construction. |
CHANGELOG.md |
Records the fix under “Fixed” in the unreleased section. |
AUTHORS |
Adds the new contributor entry. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Add a regression test that verifies the `RefreshTokenAdmin` changelist queryset uses bounded `select_related`. The test replicates the logic of `ChangeList.apply_select_related` and asserts that `qs.query.select_related` is a `dict` scoped to the declared fields rather than `True` (unbounded), which would cause Django to crawl the entire model graph.
Explicitly set `list_select_related` to only look for related applications and users when viewing the `RefreshTokenAdmin` page. When this value is not set, highly connected model graphs (i.e. those where the `user` foreign-key is related to a large number of other models) can cause runaway recursion causing the admin page to fail to load. Resolve django-oauth#1674.
ba6cc62 to
8fd54ef
Compare
dopry
approved these changes
Apr 1, 2026
Member
dopry
left a comment
There was a problem hiding this comment.
@IrishPrime excellent work! Thank you for finding this and submitting such a well formd and easy to review PR.
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.
Fixes #1674
Description of the Change
Explicitly set
list_select_relatedto only look for related applications and users when viewing theRefreshTokenAdminpage. When this value is not set, highly connected model graphs (i.e. those where theuserforeign-key is related to a large number of other models) can cause runaway recursion causing the admin page to fail to load.Add a regression test that verifies the
RefreshTokenAdminchangelist queryset uses boundedselect_related. The test replicates the logic ofChangeList.apply_select_relatedand asserts thatqs.query.select_relatedis adictscoped to the declared fields rather thanTrue(unbounded), which would cause Django to crawl the entire model graph.Checklist
CHANGELOG.mdupdated (only for user relevant changes)AUTHORS