diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 1873d449898..ce435dea818 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -182,7 +182,7 @@ def items_for_result(cl, result, form): row_class = '' try: f, attr, value = lookup_field(field_name, result, cl.model_admin) - except (AttributeError, ObjectDoesNotExist): + except ObjectDoesNotExist: result_repr = EMPTY_CHANGELIST_VALUE else: if f is None: diff --git a/tests/regressiontests/admin_views/admin.py b/tests/regressiontests/admin_views/admin.py index 293ddfebf6a..fe291ebfb8e 100644 --- a/tests/regressiontests/admin_views/admin.py +++ b/tests/regressiontests/admin_views/admin.py @@ -27,11 +27,14 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture, Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug, AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated, - RelatedPrepopulated, UndeletableObject) + RelatedPrepopulated, UndeletableObject, Simple) def callable_year(dt_value): - return dt_value.year + try: + return dt_value.year + except AttributeError: + return None callable_year.admin_order_field = 'date' @@ -575,6 +578,14 @@ class UndeletableObjectAdmin(admin.ModelAdmin): return super(UndeletableObjectAdmin, self).change_view(*args, **kwargs) +def callable_on_unknown(obj): + return obj.unknown + + +class AttributeErrorRaisingAdmin(admin.ModelAdmin): + list_display = [callable_on_unknown, ] + + site = admin.AdminSite(name="admin") site.register(Article, ArticleAdmin) site.register(CustomArticle, CustomArticleAdmin) @@ -648,6 +659,7 @@ site.register(AdminOrderedModelMethod, AdminOrderedModelMethodAdmin) site.register(AdminOrderedAdminMethod, AdminOrderedAdminMethodAdmin) site.register(AdminOrderedCallable, AdminOrderedCallableAdmin) site.register(Color2, CustomTemplateFilterColorAdmin) +site.register(Simple, AttributeErrorRaisingAdmin) # Register core models we need in our tests from django.contrib.auth.models import User, Group diff --git a/tests/regressiontests/admin_views/customadmin.py b/tests/regressiontests/admin_views/customadmin.py index 142527b022b..031fb50f0f3 100644 --- a/tests/regressiontests/admin_views/customadmin.py +++ b/tests/regressiontests/admin_views/customadmin.py @@ -49,3 +49,4 @@ site.register(models.Fabric, base_admin.FabricAdmin) site.register(models.ChapterXtra1, base_admin.ChapterXtra1Admin) site.register(User, UserLimitedAdmin) site.register(models.UndeletableObject, base_admin.UndeletableObjectAdmin) +site.register(models.Simple, base_admin.AttributeErrorRaisingAdmin) diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py index 0d5e327ecff..2c935c05a5d 100644 --- a/tests/regressiontests/admin_views/models.py +++ b/tests/regressiontests/admin_views/models.py @@ -649,3 +649,9 @@ class UndeletableObject(models.Model): Refs #10057. """ name = models.CharField(max_length=255) + + +class Simple(models.Model): + """ + Simple model with nothing on it for use in testing + """ diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index cf7d4855fb3..9f56daa7439 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -46,7 +46,7 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount, OtherStory, ComplexSortedPerson, Parent, Child, AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable, Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject, - UndeletableObject) + Simple, UndeletableObject) ERROR_MESSAGE = "Please enter the correct username and password \ @@ -578,6 +578,20 @@ class AdminViewBasicTest(TestCase): (self.urlbit, instance.pk)) self.assertNotContains(response, 'deletelink') + def test_allows_attributeerror_to_bubble_up(self): + """ + Ensure that AttributeErrors are allowed to bubble when raised inside + a change list view. + + Requires a model to be created so there's something to be displayed + + Refs: #16655, #18593, and #18747 + """ + Simple.objects.create() + with self.assertRaises(AttributeError): + self.client.get('/test_admin/%s/admin_views/simple/' % self.urlbit) + + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class AdminViewFormUrlTest(TestCase): urls = "regressiontests.admin_views.urls"