summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordizballanze <dizballanze@gmail.com>2018-02-17 11:27:46 +0300
committerTim Graham <timograham@gmail.com>2018-02-19 10:51:15 -0500
commiteb002e7892793fb9f593efaed8d3ea52a2bfc96c (patch)
treed4e964ee6fb1db3d5dd9ce9dac9ccc4d0ff94ff8
parent9b1125bfc7e2dc747128e6e7e8a2259ff1a7d39f (diff)
Fixed #29135 -- Prevented get_object/list_or_404() from hiding AttributeError raised by QuerySet filtering.
-rw-r--r--django/shortcuts.py11
-rw-r--r--tests/get_object_or_404/models.py6
-rw-r--r--tests/get_object_or_404/tests.py10
3 files changed, 21 insertions, 6 deletions
diff --git a/django/shortcuts.py b/django/shortcuts.py
index 6b35e64f4e..582aee05e5 100644
--- a/django/shortcuts.py
+++ b/django/shortcuts.py
@@ -83,14 +83,14 @@ def get_object_or_404(klass, *args, **kwargs):
one object is found.
"""
queryset = _get_queryset(klass)
- try:
- return queryset.get(*args, **kwargs)
- except AttributeError:
+ if not hasattr(queryset, 'get'):
klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
raise ValueError(
"First argument to get_object_or_404() must be a Model, Manager, "
"or QuerySet, not '%s'." % klass__name
)
+ try:
+ return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
@@ -104,14 +104,13 @@ def get_list_or_404(klass, *args, **kwargs):
arguments and keyword arguments are used in the filter() query.
"""
queryset = _get_queryset(klass)
- try:
- obj_list = list(queryset.filter(*args, **kwargs))
- except AttributeError:
+ if not hasattr(queryset, 'filter'):
klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
raise ValueError(
"First argument to get_list_or_404() must be a Model, Manager, or "
"QuerySet, not '%s'." % klass__name
)
+ obj_list = list(queryset.filter(*args, **kwargs))
if not obj_list:
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
return obj_list
diff --git a/tests/get_object_or_404/models.py b/tests/get_object_or_404/models.py
index b18918a853..04f22dd049 100644
--- a/tests/get_object_or_404/models.py
+++ b/tests/get_object_or_404/models.py
@@ -25,11 +25,17 @@ class ArticleManager(models.Manager):
return super().get_queryset().filter(authors__name__icontains='sir')
+class AttributeErrorManager(models.Manager):
+ def get_queryset(self):
+ raise AttributeError('AttributeErrorManager')
+
+
class Article(models.Model):
authors = models.ManyToManyField(Author)
title = models.CharField(max_length=50)
objects = models.Manager()
by_a_sir = ArticleManager()
+ attribute_error_objects = AttributeErrorManager()
def __str__(self):
return self.title
diff --git a/tests/get_object_or_404/tests.py b/tests/get_object_or_404/tests.py
index a72b766524..075f9a08e1 100644
--- a/tests/get_object_or_404/tests.py
+++ b/tests/get_object_or_404/tests.py
@@ -94,3 +94,13 @@ class GetObjectOr404Tests(TestCase):
msg = "First argument to get_list_or_404() must be a Model, Manager, or QuerySet, not 'list'."
with self.assertRaisesMessage(ValueError, msg):
get_list_or_404([Article], title__icontains="Run")
+
+ def test_get_object_or_404_queryset_attribute_error(self):
+ """AttributeError raised by QuerySet.get() isn't hidden."""
+ with self.assertRaisesMessage(AttributeError, 'AttributeErrorManager'):
+ get_object_or_404(Article.attribute_error_objects, id=42)
+
+ def test_get_list_or_404_queryset_attribute_error(self):
+ """AttributeError raised by QuerySet.filter() isn't hidden."""
+ with self.assertRaisesMessage(AttributeError, 'AttributeErrorManager'):
+ get_list_or_404(Article.attribute_error_objects, title__icontains='Run')