Fixed #29804 -- Added 'did you mean' suggestions for unsupported lookup error.

This commit is contained in:
Abhinav Patil 2018-09-29 03:22:27 -04:00 committed by Tim Graham
parent f83a689f61
commit bf01994a5c
3 changed files with 26 additions and 3 deletions

View File

@ -9,6 +9,7 @@ answer newbie questions, and generally made Django that much better:
Aaron Swartz <http://www.aaronsw.com/> Aaron Swartz <http://www.aaronsw.com/>
Aaron T. Myers <atmyers@gmail.com> Aaron T. Myers <atmyers@gmail.com>
Abeer Upadhyay <ab.esquarer@gmail.com> Abeer Upadhyay <ab.esquarer@gmail.com>
Abhinav Patil <https://github.com/ubadub/>
Abhishek Gautam <abhishekg1128@yahoo.com> Abhishek Gautam <abhishekg1128@yahoo.com>
Adam Bogdał <adam@bogdal.pl> Adam Bogdał <adam@bogdal.pl>
Adam Donaghy Adam Donaghy

View File

@ -6,6 +6,7 @@ themselves do not have to (and could be backed by things other than SQL
databases). The abstraction barrier only works one way: this module has to know databases). The abstraction barrier only works one way: this module has to know
all about the internals of models in order to get the information it needs. all about the internals of models in order to get the information it needs.
""" """
import difflib
import functools import functools
from collections import Counter, OrderedDict, namedtuple from collections import Counter, OrderedDict, namedtuple
from collections.abc import Iterator, Mapping from collections.abc import Iterator, Mapping
@ -1140,10 +1141,16 @@ class Query:
if transform_class: if transform_class:
return transform_class(lhs) return transform_class(lhs)
else: else:
output_field = lhs.output_field.__class__
suggested_lookups = difflib.get_close_matches(name, output_field.get_lookups())
if suggested_lookups:
suggestion = ', perhaps you meant %s?' % ' or '.join(suggested_lookups)
else:
suggestion = '.'
raise FieldError( raise FieldError(
"Unsupported lookup '%s' for %s or join on the field not " "Unsupported lookup '%s' for %s or join on the field not "
"permitted." % "permitted%s" % (name, output_field.__name__, suggestion)
(name, lhs.output_field.__class__.__name__)) )
def build_filter(self, filter_expr, branch_negated=False, current_negated=False, def build_filter(self, filter_expr, branch_negated=False, current_negated=False,
can_reuse=None, allow_joins=True, split_subq=True, can_reuse=None, allow_joins=True, split_subq=True,

View File

@ -569,13 +569,28 @@ class LookupTests(TestCase):
): ):
Article.objects.filter(pub_date_year='2005').count() Article.objects.filter(pub_date_year='2005').count()
def test_unsupported_lookups(self):
with self.assertRaisesMessage( with self.assertRaisesMessage(
FieldError, FieldError,
"Unsupported lookup 'starts' for CharField or join on the field " "Unsupported lookup 'starts' for CharField or join on the field "
"not permitted." "not permitted, perhaps you meant startswith or istartswith?"
): ):
Article.objects.filter(headline__starts='Article') Article.objects.filter(headline__starts='Article')
with self.assertRaisesMessage(
FieldError,
"Unsupported lookup 'is_null' for DateTimeField or join on the field "
"not permitted, perhaps you meant isnull?"
):
Article.objects.filter(pub_date__is_null=True)
with self.assertRaisesMessage(
FieldError,
"Unsupported lookup 'gobbledygook' for DateTimeField or join on the field "
"not permitted."
):
Article.objects.filter(pub_date__gobbledygook='blahblah')
def test_relation_nested_lookup_error(self): def test_relation_nested_lookup_error(self):
# An invalid nested lookup on a related field raises a useful error. # An invalid nested lookup on a related field raises a useful error.
msg = 'Related Field got invalid lookup: editor' msg = 'Related Field got invalid lookup: editor'