Skip to content

Fix DALFRelatedFieldAjax filter repopulation bug - #21

Merged
vigo merged 6 commits into
mainfrom
issue-18
Jan 24, 2026
Merged

Fix DALFRelatedFieldAjax filter repopulation bug#21
vigo merged 6 commits into
mainfrom
issue-18

Conversation

@vigo

@vigo vigo commented Jan 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix filter input not repopulating when selected value is beyond first 20 results (pagination limit)
  • Pass selected_text from Python to template, eliminating unnecessary AJAX call
  • Gracefully handle deleted/invalid selected values

Fixes #18

Test plan

  • Run pytest - all 4 tests pass
  • Run pre-commit hooks - all pass
  • Manual test with 20+ categories, selecting one beyond first page
  • Test with deleted category ID in URL - should not error

🤖 Generated with Claude Code

Pass selected_text from Python to template to avoid AJAX call that only
returns first 20 results. Selected values beyond pagination limit now
display correctly on page reload.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@codecov-commenter

codecov-commenter commented Jan 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (900f40d) to head (38d6bc0).
⚠️ Report is 50 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main       #21   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         3           
  Lines           47        54    +7     
=========================================
+ Hits            47        54    +7     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

vigo and others added 2 commits January 24, 2026 23:04
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes DALFRelatedFieldAjax filter UI repopulation by providing the selected option’s display text server-side, avoiding a fragile client-side “first page” lookup.

Changes:

  • Add selected_text computation in DALFRelatedFieldAjax and expose it to the template.
  • Render selected_text into the AJAX filter template and use it to preselect the Select2 option without an extra AJAX request.
  • Add tests covering repopulation and a deleted-selected-value scenario.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

File Description
tests/testproject/testapp/tests.py Adds regression tests for selected-text repopulation and deleted-value handling.
src/dalf/templates/admin/filter/django_admin_list_filter_ajax.html Adds a hidden field to pass selected_text to the frontend.
src/dalf/static/admin/js/django_admin_list_filter.js Uses selected_text to prepopulate Select2 without an extra AJAX call.
src/dalf/admin.py Computes selected_text from the related object and includes it in filter template params.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/dalf/admin.py Outdated
obj = related_model.objects.get(pk=self.selected_value)
self.selected_text = str(obj)
except (related_model.DoesNotExist, ValueError):
self.selected_value = None

Copilot AI Jan 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On DoesNotExist you set self.selected_value = None, but the query parameter is still present so the changelist remains filtered while the UI shows “All” and the clear button won’t appear (user can get stuck with an un-clearable filter). Instead, keep selected_value and set selected_text to a safe fallback (e.g., the raw ID or a localized “(deleted)” label) so Select2 can render a selected option and allow clearing.

Suggested change
self.selected_value = None
# Keep selected_value so the filter state matches the query parameter,
# but use a safe fallback label so the UI can render and clear it.
self.selected_text = str(self.selected_value)

Copilot uses AI. Check for mistakes.
Comment thread src/dalf/admin.py Outdated
Comment on lines +91 to +96
try:
related_model = field.remote_field.model
obj = related_model.objects.get(pk=self.selected_value)
self.selected_text = str(obj)
except (related_model.DoesNotExist, ValueError):
self.selected_value = None

Copilot AI Jan 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selected_text is derived via a direct related_model.objects.get(pk=...) without going through the admin/autocomplete permission/queryset logic. This can expose the string representation of related objects a user may not have permission to view (and may bypass any admin/queryset restrictions that autocomplete would enforce). Consider resolving the related object via the related model’s registered ModelAdmin (e.g., model_admin.admin_site._registry[related_model]) and its has_view_permission/get_queryset(request) (or fall back to leaving selected_text empty when not permitted).

Suggested change
try:
related_model = field.remote_field.model
obj = related_model.objects.get(pk=self.selected_value)
self.selected_text = str(obj)
except (related_model.DoesNotExist, ValueError):
self.selected_value = None
related_model = field.remote_field.model
# Resolve via the related model's ModelAdmin to respect admin permissions
related_admin = model_admin.admin_site._registry.get(related_model)
if related_admin is not None:
qs = related_admin.get_queryset(request)
try:
obj = qs.get(pk=self.selected_value)
except (related_model.DoesNotExist, ValueError):
# Keep behavior consistent: clear value if object does not exist
self.selected_value = None
else:
if related_admin.has_view_permission(request, obj):
self.selected_text = str(obj)
else:
# User is not allowed to view this object; do not expose its string
self.selected_text = None
# If there is no registered ModelAdmin for the related model,
# we do not attempt a direct objects.get(...) to avoid bypassing permissions.

Copilot uses AI. Check for mistakes.
vigo and others added 3 commits January 24, 2026 23:09
When the selected object is deleted, keep selected_value so the filter
state matches the URL parameter. Use raw ID as fallback text so users
can still clear the filter via Select2.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vigo
vigo merged commit 5b47e23 into main Jan 24, 2026
8 checks passed
@vigo
vigo deleted the issue-18 branch January 24, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Repopulation of filter input broken for DALFRelatedFieldAjax

3 participants