From ccd1bb0d81381b5611fb5caf2c4ebe5927fe2095 Mon Sep 17 00:00:00 2001 From: Travis Swicegood Date: Sat, 8 Sep 2012 11:18:08 -0400 Subject: [PATCH] Remove Admin's swallowing of AttributeError (#16655, #18593, #18747) During the new-admin changes, catching of AttributeError was added to the admin. This patch removes that as it's no longer possible to add a value to a ModelAdmin that is not available. Adding an attribute that can not be called causes an ImproperlyConfigured exception to be raised. --- django/contrib/admin/templatetags/admin_list.py | 2 +- tests/regressiontests/admin_views/admin.py | 16 ++++++++++++++-- tests/regressiontests/admin_views/customadmin.py | 1 + tests/regressiontests/admin_views/models.py | 6 ++++++ tests/regressiontests/admin_views/tests.py | 16 +++++++++++++++- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 1873d44989..ce435dea81 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 293ddfebf6..fe291ebfb8 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 142527b022..031fb50f0f 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 0d5e327ecf..2c935c05a5 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 cf7d4855fb..9f56daa743 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"