Fixed #21619 -- Made SingleObjectMixin.get_object catch a more precise exception.

Thanks to Keryn Knight for the report.
This commit is contained in:
Peter Harley 2013-12-14 23:15:35 +00:00 committed by Baptiste Mispelon
parent a1bc3683ff
commit cdd6617da6
5 changed files with 29 additions and 4 deletions

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.core.exceptions import ImproperlyConfigured
from django.db import models from django.db import models
from django.http import Http404 from django.http import Http404
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -50,7 +50,7 @@ class SingleObjectMixin(ContextMixin):
try: try:
# Get the single item from the filtered queryset # Get the single item from the filtered queryset
obj = queryset.get() obj = queryset.get()
except ObjectDoesNotExist: except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") % raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name}) {'verbose_name': queryset.model._meta.verbose_name})
return obj return obj

View File

@ -1,5 +1,7 @@
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models from django.db import models
from django.db.models import QuerySet
from django.db.models.manager import BaseManager
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
@ -31,6 +33,13 @@ class Author(models.Model):
return self.name return self.name
class DoesNotExistQuerySet(QuerySet):
def get(self, *args, **kwargs):
raise Author.DoesNotExist
DoesNotExistBookManager = BaseManager.from_queryset(DoesNotExistQuerySet)
@python_2_unicode_compatible @python_2_unicode_compatible
class Book(models.Model): class Book(models.Model):
name = models.CharField(max_length=300) name = models.CharField(max_length=300)
@ -39,6 +48,9 @@ class Book(models.Model):
authors = models.ManyToManyField(Author) authors = models.ManyToManyField(Author)
pubdate = models.DateField() pubdate = models.DateField()
objects = models.Manager()
does_not_exist = DoesNotExistBookManager()
class Meta: class Meta:
ordering = ['-pubdate'] ordering = ['-pubdate']

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.test import TestCase from django.test import TestCase
from django.views.generic.base import View from django.views.generic.base import View
@ -25,6 +25,13 @@ class DetailViewTest(TestCase):
self.assertEqual(res.context['author'], Author.objects.get(pk=1)) self.assertEqual(res.context['author'], Author.objects.get(pk=1))
self.assertTemplateUsed(res, 'generic_views/author_detail.html') self.assertTemplateUsed(res, 'generic_views/author_detail.html')
def test_detail_missing_object(self):
res = self.client.get('/detail/author/500/')
self.assertEqual(res.status_code, 404)
def test_detail_object_does_not_exist(self):
self.assertRaises(ObjectDoesNotExist, self.client.get, '/detail/doesnotexist/1/')
def test_detail_by_custom_pk(self): def test_detail_by_custom_pk(self):
res = self.client.get('/detail/author/bycustompk/1/') res = self.client.get('/detail/author/bycustompk/1/')
self.assertEqual(res.status_code, 200) self.assertEqual(res.status_code, 200)

View File

@ -55,7 +55,8 @@ urlpatterns = patterns('',
views.AuthorDetail.as_view(queryset=None)), views.AuthorDetail.as_view(queryset=None)),
(r'^detail/nonmodel/1/$', (r'^detail/nonmodel/1/$',
views.NonModelDetail.as_view()), views.NonModelDetail.as_view()),
(r'^detail/doesnotexist/(?P<pk>\d+)/$',
views.ObjectDoesNotExistDetail.as_view()),
# FormView # FormView
(r'^contact/$', (r'^contact/$',
views.ContactView.as_view()), views.ContactView.as_view()),

View File

@ -300,3 +300,8 @@ class NonModelDetail(generic.DetailView):
def get_object(self, queryset=None): def get_object(self, queryset=None):
return NonModel() return NonModel()
class ObjectDoesNotExistDetail(generic.DetailView):
def get_queryset(self):
return Book.does_not_exist.all()