Add more explanatory FieldLookupError
This commit is contained in:
parent
bd25121332
commit
f61d7a7324
|
@ -0,0 +1,9 @@
|
|||
|
||||
from django.core.exceptions import FieldError
|
||||
|
||||
|
||||
class FieldLookupError(FieldError):
|
||||
def __init__(self, model_field, lookup_expr):
|
||||
super(FieldLookupError, self).__init__(
|
||||
"Unsupported lookup '%s' for field '%s'." % (lookup_expr, model_field)
|
||||
)
|
|
@ -1,12 +1,14 @@
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db import models
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
from django.db.models.expressions import Expression
|
||||
from django.db.models.fields import FieldDoesNotExist
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
from django.utils import timezone
|
||||
from django.utils import six, timezone
|
||||
|
||||
from .compat import remote_model
|
||||
from .exceptions import FieldLookupError
|
||||
|
||||
|
||||
def try_dbfield(fn, field_class):
|
||||
|
@ -78,22 +80,25 @@ def resolve_field(model_field, lookup_expr):
|
|||
|
||||
assert len(lookups) > 0
|
||||
|
||||
while lookups:
|
||||
name = lookups[0]
|
||||
# If there is just one part left, try first get_lookup() so
|
||||
# that if the lhs supports both transform and lookup for the
|
||||
# name, then lookup will be picked.
|
||||
if len(lookups) == 1:
|
||||
final_lookup = lhs.get_lookup(name)
|
||||
if not final_lookup:
|
||||
# We didn't find a lookup. We are going to interpret
|
||||
# the name as transform, and do an Exact lookup against
|
||||
# it.
|
||||
lhs = query.try_transform(lhs, name, lookups)
|
||||
final_lookup = lhs.get_lookup('exact')
|
||||
return lhs.output_field, final_lookup.lookup_name
|
||||
lhs = query.try_transform(lhs, name, lookups)
|
||||
lookups = lookups[1:]
|
||||
try:
|
||||
while lookups:
|
||||
name = lookups[0]
|
||||
# If there is just one part left, try first get_lookup() so
|
||||
# that if the lhs supports both transform and lookup for the
|
||||
# name, then lookup will be picked.
|
||||
if len(lookups) == 1:
|
||||
final_lookup = lhs.get_lookup(name)
|
||||
if not final_lookup:
|
||||
# We didn't find a lookup. We are going to interpret
|
||||
# the name as transform, and do an Exact lookup against
|
||||
# it.
|
||||
lhs = query.try_transform(lhs, name, lookups)
|
||||
final_lookup = lhs.get_lookup('exact')
|
||||
return lhs.output_field, final_lookup.lookup_name
|
||||
lhs = query.try_transform(lhs, name, lookups)
|
||||
lookups = lookups[1:]
|
||||
except FieldError as e:
|
||||
six.raise_from(FieldLookupError(model_field, lookup_expr), e)
|
||||
|
||||
|
||||
def handle_timezone(value):
|
||||
|
|
|
@ -28,6 +28,7 @@ from django_filters.filters import NumberFilter
|
|||
from django_filters.filters import RangeFilter
|
||||
from django_filters.filters import TimeRangeFilter
|
||||
# from django_filters.widgets import LinkWidget
|
||||
from django_filters.exceptions import FieldLookupError
|
||||
|
||||
from .models import User
|
||||
from .models import Comment
|
||||
|
@ -1718,3 +1719,16 @@ class MiscFilterSetTests(TestCase):
|
|||
f = F({'status': '2'}, queryset=qs)
|
||||
self.assertEqual(len(f.qs), 2)
|
||||
self.assertEqual(f.count(), 2)
|
||||
|
||||
def test_invalid_field_lookup(self):
|
||||
# We want to ensure that non existent lookups (or just simple misspellings)
|
||||
# throw a useful exception containg the field and lookup expr.
|
||||
with self.assertRaises(FieldLookupError) as context:
|
||||
class F(FilterSet):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = {'username': ['flub']}
|
||||
|
||||
exc = str(context.exception)
|
||||
self.assertIn('tests.User.username', exc)
|
||||
self.assertIn('flub', exc)
|
||||
|
|
|
@ -5,9 +5,9 @@ import django
|
|||
from django.test import TestCase
|
||||
from django.db import models
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
from django.core.exceptions import FieldError
|
||||
|
||||
from django_filters.utils import get_model_field, resolve_field
|
||||
from django_filters.exceptions import FieldLookupError
|
||||
|
||||
from .models import User
|
||||
from .models import Article
|
||||
|
@ -156,11 +156,19 @@ class ResolveFieldTests(TestCase):
|
|||
def test_invalid_lookup_expression(self):
|
||||
model_field = Article._meta.get_field('published')
|
||||
|
||||
with self.assertRaises(FieldError):
|
||||
field, lookup = resolve_field(model_field, 'invalid_lookup')
|
||||
with self.assertRaises(FieldLookupError) as context:
|
||||
resolve_field(model_field, 'invalid_lookup')
|
||||
|
||||
exc = str(context.exception)
|
||||
self.assertIn(str(model_field), exc)
|
||||
self.assertIn('invalid_lookup', exc)
|
||||
|
||||
def test_invalid_transformed_lookup_expression(self):
|
||||
model_field = Article._meta.get_field('published')
|
||||
|
||||
with self.assertRaises(FieldError):
|
||||
field, lookup = resolve_field(model_field, 'date__invalid_lookup')
|
||||
with self.assertRaises(FieldLookupError) as context:
|
||||
resolve_field(model_field, 'date__invalid_lookup')
|
||||
|
||||
exc = str(context.exception)
|
||||
self.assertIn(str(model_field), exc)
|
||||
self.assertIn('date__invalid_lookup', exc)
|
||||
|
|
Loading…
Reference in New Issue