Fixed #3511 -- Changed QuerySet.get() to return a MultipleObjectsReturned exception, rather than an assertion error. Thanks, Gary Wilson and cheeming.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@6838 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-12-02 18:21:07 +00:00
parent 5e5768ae83
commit 805c364fcf
6 changed files with 13 additions and 6 deletions

View File

@ -4,6 +4,10 @@ class ObjectDoesNotExist(Exception):
"The requested object does not exist" "The requested object does not exist"
silent_variable_failure = True silent_variable_failure = True
class MultipleObjectsReturned(Exception):
"The query returned multiple objects when only one was expected."
pass
class SuspiciousOperation(Exception): class SuspiciousOperation(Exception):
"The user did something suspicious" "The user did something suspicious"
pass pass

View File

@ -1,7 +1,7 @@
import django.db.models.manipulators import django.db.models.manipulators
import django.db.models.manager import django.db.models.manager
from django.core import validators from django.core import validators
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist
from django.db.models.fields.related import OneToOneRel, ManyToOneRel from django.db.models.fields.related import OneToOneRel, ManyToOneRel
from django.db.models.query import delete_objects from django.db.models.query import delete_objects
@ -35,6 +35,8 @@ class ModelBase(type):
new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')}) new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')})
new_class.add_to_class('_meta', Options(attrs.pop('Meta', None))) new_class.add_to_class('_meta', Options(attrs.pop('Meta', None)))
new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {})) new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}))
new_class.add_to_class('MultipleObjectsReturned',
types.ClassType('MultipleObjectsReturned', (MultipleObjectsReturned, ), {}))
# Build complete list of parents # Build complete list of parents
for base in bases: for base in bases:

View File

@ -261,7 +261,8 @@ class _QuerySet(object):
obj_list = list(clone) obj_list = list(clone)
if len(obj_list) < 1: if len(obj_list) < 1:
raise self.model.DoesNotExist, "%s matching query does not exist." % self.model._meta.object_name raise self.model.DoesNotExist, "%s matching query does not exist." % self.model._meta.object_name
assert len(obj_list) == 1, "get() returned more than one %s -- it returned %s! Lookup parameters were %s" % (self.model._meta.object_name, len(obj_list), kwargs) elif len(obj_list) > 1:
raise self.model.MultipleObjectsReturned, "get() returned more than one %s -- it returned %s! Lookup parameters were %s" % (self.model._meta.object_name, len(obj_list), kwargs)
return obj_list[0] return obj_list[0]
def create(self, **kwargs): def create(self, **kwargs):

View File

@ -38,7 +38,7 @@ def get_object_or_404(klass, *args, **kwargs):
klass may be a Model, Manager, or QuerySet object. All other passed klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query. arguments and keyword arguments are used in the get() query.
Note: Like with get(), an AssertionError will be raised if more than one Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
object is found. object is found.
""" """
queryset = _get_queryset(klass) queryset = _get_queryset(klass)

View File

@ -98,8 +98,8 @@ This example is equivalent to::
except MyModel.DoesNotExist: except MyModel.DoesNotExist:
raise Http404 raise Http404
Note: As with ``get()``, an ``AssertionError`` will be raised if more than Note: As with ``get()``, an ``MultipleObjectsReturned`` exception will be
one object is found. raised if more than one object is found.
.. _get(): ../db-api/#get-kwargs .. _get(): ../db-api/#get-kwargs

View File

@ -78,7 +78,7 @@ Http404: No Article matches the given query.
>>> get_object_or_404(Author.objects.all()) >>> get_object_or_404(Author.objects.all())
Traceback (most recent call last): Traceback (most recent call last):
... ...
AssertionError: get() returned more than one Author -- it returned ...! Lookup parameters were {} MultipleObjectsReturned: get() returned more than one Author -- it returned ...! Lookup parameters were {}
# Using an EmptyQuerySet raises a Http404 error. # Using an EmptyQuerySet raises a Http404 error.
>>> get_object_or_404(Article.objects.none(), title__contains="Run") >>> get_object_or_404(Article.objects.none(), title__contains="Run")