diff --git a/AUTHORS b/AUTHORS index ab4415fb04..461182d77b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -144,6 +144,7 @@ answer newbie questions, and generally made Django that much better: Ricardo Javier Cárdenes Medina Jeremy Carbaugh Graham Carlyle + Juan Catalano Antonio Cavedoni cedric@terramater.net Chris Chamberlin diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index f53d655bfc..1b215879d1 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -1537,7 +1537,7 @@ class ModelAdmin(BaseModelAdmin): from django.contrib.admin.models import LogEntry # First check if the user can see this history. model = self.model - obj = get_object_or_404(model, pk=unquote(object_id)) + obj = get_object_or_404(self.get_queryset(request), pk=unquote(object_id)) if not self.has_change_permission(request, obj): raise PermissionDenied diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py index b2da23f08e..5649a3c492 100644 --- a/tests/admin_views/admin.py +++ b/tests/admin_views/admin.py @@ -30,7 +30,7 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture, AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated, RelatedPrepopulated, UndeletableObject, UnchangeableObject, UserMessenger, Simple, Choice, - ShortMessage, Telegram) + ShortMessage, Telegram, FilteredManager) def callable_year(dt_value): @@ -674,6 +674,12 @@ def callable_on_unknown(obj): class AttributeErrorRaisingAdmin(admin.ModelAdmin): list_display = [callable_on_unknown, ] + +class CustomManagerAdmin(admin.ModelAdmin): + def get_queryset(self, request): + return FilteredManager.objects + + class MessageTestingAdmin(admin.ModelAdmin): actions = ["message_debug", "message_info", "message_success", "message_warning", "message_error", "message_extra_tags"] @@ -773,6 +779,7 @@ site.register(Question) site.register(Answer) site.register(PrePopulatedPost, PrePopulatedPostAdmin) site.register(ComplexSortedPerson, ComplexSortedPersonAdmin) +site.register(FilteredManager, CustomManagerAdmin) site.register(PluggableSearchPerson, PluggableSearchPersonAdmin) site.register(PrePopulatedPostLargeSlug, PrePopulatedPostLargeSlugAdmin) site.register(AdminOrderedField, AdminOrderedFieldAdmin) diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py index 6483fc8717..c09411dc27 100644 --- a/tests/admin_views/models.py +++ b/tests/admin_views/models.py @@ -693,3 +693,14 @@ class Simple(models.Model): class Choice(models.Model): choice = models.IntegerField(blank=True, null=True, choices=((1, 'Yes'), (0, 'No'), (None, 'No opinion'))) + +class _Manager(models.Manager): + def get_queryset(self): + return super(_Manager, self).get_queryset().filter(pk__gt=1) + +class FilteredManager(models.Model): + def __str__(self): + return "PK=%d" % self.pk + + pk_gt_1 = _Manager() + objects = models.Manager() diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index fc1e18a47f..718b831846 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -48,7 +48,7 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable, Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject, Simple, UndeletableObject, UnchangeableObject, Choice, ShortMessage, - Telegram, Pizza, Topping) + Telegram, Pizza, Topping, FilteredManager) from .admin import site, site2 @@ -2656,6 +2656,12 @@ class AdminCustomQuerysetTest(TestCase): def setUp(self): self.client.login(username='super', password='secret') self.pks = [EmptyModel.objects.create().id for i in range(3)] + self.super_login = { + REDIRECT_FIELD_NAME: '/test_admin/admin/', + LOGIN_FORM_KEY: 1, + 'username': 'super', + 'password': 'secret', + } def test_changelist_view(self): response = self.client.get('/test_admin/admin/admin_views/emptymodel/') @@ -2873,6 +2879,20 @@ class AdminCustomQuerysetTest(TestCase): html=True ) + def test_history_view_custom_qs(self): + """ + Ensure that custom querysets are considered for the admin history view. + Refs #21013. + """ + self.client.post('/test_admin/admin/', self.super_login) + FilteredManager.objects.create(pk=1) + FilteredManager.objects.create(pk=2) + response = self.client.get('/test_admin/admin/admin_views/filteredmanager/') + self.assertContains(response, "PK=1") + self.assertContains(response, "PK=2") + self.assertEqual(self.client.get('/test_admin/admin/admin_views/filteredmanager/1/history/').status_code, 200) + self.assertEqual(self.client.get('/test_admin/admin/admin_views/filteredmanager/2/history/').status_code, 200) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminInlineFileUploadTest(TestCase):