1
0
mirror of https://github.com/django/django.git synced 2025-07-05 18:29:11 +00:00

queryset-refactor: Fixed #6664. Calling list() no longer swallows field errors.

This is slightly backwards incompatible with previous behaviour if you were
doing Tricky Stuff(tm) -- the exception type has changed if you try to create a
bad queryset.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7163 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-02-27 00:44:44 +00:00
parent fc4c0f7b39
commit 014373b459
11 changed files with 27 additions and 20 deletions

View File

@ -27,3 +27,8 @@ class MiddlewareNotUsed(Exception):
class ImproperlyConfigured(Exception):
"Django is somehow improperly configured"
pass
class FieldError(Exception):
"""Some kind of problem with a model field."""
pass

View File

@ -6,7 +6,7 @@ from itertools import izip
import django.db.models.manipulators
import django.db.models.manager
from django.core import validators
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist
from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField
from django.db.models.query import delete_objects, Q
@ -101,7 +101,7 @@ class ModelBase(type):
names = [f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many]
for field in base._meta.local_fields:
if field.name in names:
raise TypeError('Local field %r in class %r clashes with field of similar name from abstract base class %r'
raise FieldError('Local field %r in class %r clashes with field of similar name from abstract base class %r'
% (field.name, name, base.__name__))
new_class.add_to_class(field.name, field)

View File

@ -19,6 +19,7 @@ from django.db.models.sql.where import WhereNode, EverythingNode, AND, OR
from django.db.models.sql.datastructures import Count, Date
from django.db.models.fields import FieldDoesNotExist, Field, related
from django.contrib.contenttypes import generic
from django.core.exceptions import FieldError
from datastructures import EmptyResultSet
try:
@ -548,7 +549,7 @@ class Query(object):
already_seen = {}
join_tuple = tuple([tuple(j) for j in joins])
if join_tuple in already_seen:
raise TypeError('Infinite loop caused by ordering.')
raise FieldError('Infinite loop caused by ordering.')
already_seen[join_tuple] = True
results = []
@ -735,7 +736,7 @@ class Query(object):
arg, value = filter_expr
parts = arg.split(LOOKUP_SEP)
if not parts:
raise TypeError("Cannot parse keyword query %r" % arg)
raise FieldError("Cannot parse keyword query %r" % arg)
# Work out the lookup type and remove it from 'parts', if necessary.
if len(parts) == 1 or parts[-1] not in self.query_terms:
@ -867,7 +868,7 @@ class Query(object):
field, model, direct, m2m = opts.get_field_by_name(name)
except FieldDoesNotExist:
names = opts.get_all_field_names()
raise TypeError("Cannot resolve keyword %r into field. "
raise FieldError("Cannot resolve keyword %r into field. "
"Choices are: %s" % (name, ", ".join(names)))
if model:
# The field lives on a base class of the current model.
@ -972,7 +973,7 @@ class Query(object):
joins.append([alias])
if pos != len(names) - 1:
raise TypeError("Join on field %r not permitted." % name)
raise FieldError("Join on field %r not permitted." % name)
return field, target, opts, joins
@ -1033,7 +1034,7 @@ class Query(object):
if not ORDER_PATTERN.match(item):
errors.append(item)
if errors:
raise TypeError('Invalid order_by arguments: %s' % errors)
raise FieldError('Invalid order_by arguments: %s' % errors)
if ordering:
self.order_by.extend(ordering)
else:
@ -1228,7 +1229,7 @@ class UpdateQuery(Query):
for alias in alias_list:
if self.alias_map[alias][ALIAS_REFCOUNT]:
if table:
raise TypeError('Updates can only access a single database table at a time.')
raise FieldError('Updates can only access a single database table at a time.')
table = alias
else:
table = self.tables[0]
@ -1271,7 +1272,7 @@ class UpdateQuery(Query):
field, model, direct, m2m = self.model._meta.get_field_by_name(name)
if not direct or m2m:
# Can only update non-relation fields and foreign keys.
raise TypeError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field)
raise fieldError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field)
if field.rel and isinstance(val, Model):
val = val.pk
self.values.append((field.column, val))

View File

@ -71,7 +71,7 @@ __test__ = {'API_TESTS':"""
>>> Author.objects.filter(firstname__exact='John')
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'firstname' into field. Choices are: article, first_name, id, last_name
FieldError: Cannot resolve keyword 'firstname' into field. Choices are: article, first_name, id, last_name
>>> a = Author.objects.get(last_name__exact='Smith')
>>> a.first_name

View File

@ -5,6 +5,7 @@ Tests for field subclassing.
from django.db import models
from django.utils.encoding import force_unicode
from django.core import serializers
from django.core.exceptions import FieldError
class Small(object):
"""
@ -50,7 +51,7 @@ class SmallField(models.Field):
return [force_unicode(v) for v in value]
if lookup_type == 'isnull':
return []
raise TypeError('Invalid lookup type: %r' % lookup_type)
raise FieldError('Invalid lookup type: %r' % lookup_type)
def flatten_data(self, follow, obj=None):
return {self.attname: force_unicode(self._get_val_from_obj(obj))}
@ -94,7 +95,7 @@ True
>>> MyModel.objects.filter(data__lt=s)
Traceback (most recent call last):
...
TypeError: Invalid lookup type: 'lt'
FieldError: Invalid lookup type: 'lt'
# Serialization works, too.
>>> stream = serializers.serialize("json", MyModel.objects.all())

View File

@ -270,12 +270,12 @@ DoesNotExist: Article matching query does not exist.
>>> Article.objects.filter(pub_date_year='2005').count()
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'pub_date_year' into field. Choices are: headline, id, pub_date
FieldError: Cannot resolve keyword 'pub_date_year' into field. Choices are: headline, id, pub_date
>>> Article.objects.filter(headline__starts='Article')
Traceback (most recent call last):
...
TypeError: Join on field 'headline' not permitted.
FieldError: Join on field 'headline' not permitted.
# Create some articles with a bit more interesting headlines for testing field lookups:
>>> now = datetime.now()

View File

@ -179,13 +179,13 @@ False
>>> Article.objects.filter(reporter_id__exact=1)
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'reporter_id' into field. Choices are: headline, id, pub_date, reporter
FieldError: Cannot resolve keyword 'reporter_id' into field. Choices are: headline, id, pub_date, reporter
# You need to specify a comparison clause
>>> Article.objects.filter(reporter_id=1)
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'reporter_id' into field. Choices are: headline, id, pub_date, reporter
FieldError: Cannot resolve keyword 'reporter_id' into field. Choices are: headline, id, pub_date, reporter
# You can also instantiate an Article by passing
# the Reporter's ID instead of a Reporter object.

View File

@ -148,7 +148,7 @@ Test constructor for Restaurant.
>>> Restaurant.objects.filter(supplier__name='foo')
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'supplier' into field. Choices are: address, id, italianrestaurant, lot, name, place_ptr, provider, rating, serves_hot_dogs, serves_pizza
FieldError: Cannot resolve keyword 'supplier' into field. Choices are: address, id, italianrestaurant, lot, name, place_ptr, provider, rating, serves_hot_dogs, serves_pizza
# Parent fields can be used directly in filters on the child model.
>>> Restaurant.objects.filter(name='Demon Dogs')

View File

@ -55,5 +55,5 @@ __test__ = {'API_TESTS':"""
>>> Poll.objects.get(choice__name__exact="This is the answer")
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'choice' into field. Choices are: creator, id, poll_choice, question, related_choice
FieldError: Cannot resolve keyword 'choice' into field. Choices are: creator, id, poll_choice, question, related_choice
"""}

View File

@ -37,7 +37,7 @@ Excluding the previous result returns everything.
>>> Choice.objects.filter(foo__exact=None)
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'foo' into field. Choices are: choice, id, poll
FieldError: Cannot resolve keyword 'foo' into field. Choices are: choice, id, poll
# Can't use None on anything other than __exact
>>> Choice.objects.filter(id__gt=None)

View File

@ -394,7 +394,7 @@ Bug #2076
>>> LoopX.objects.all()
Traceback (most recent call last):
...
TypeError: Infinite loop caused by ordering.
FieldError: Infinite loop caused by ordering.
# If the remote model does not have a default ordering, we order by its 'id'
# field.