diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 7524a3582d..d8c711d18f 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1370,9 +1370,13 @@ class Query(object): try: field, model, direct, m2m = opts.get_field_by_name(name) except FieldDoesNotExist: - # We didn't found the current field, so move position back + # We didn't find the current field, so move position back # one step. pos -= 1 + if pos == -1 or fail_on_missing: + available = opts.get_all_field_names() + list(self.aggregate_select) + raise FieldError("Cannot resolve keyword %r into field. " + "Choices are: %s" % (name, ", ".join(available))) break # Check if we need any joins for concrete inheritance cases (the # field lives in parent, but we are currently in one of its @@ -1412,16 +1416,13 @@ class Query(object): # Local non-relational field. final_field = field targets = (field,) + if fail_on_missing and pos + 1 != len(names): + raise FieldError( + "Cannot resolve keyword %r into field. Join on '%s'" + " not permitted." % (names[pos + 1], name)) break - if pos == -1 or (fail_on_missing and pos + 1 != len(names)): - self.raise_field_error(opts, name) return path, final_field, targets, names[pos + 1:] - def raise_field_error(self, opts, name): - available = opts.get_all_field_names() + list(self.aggregate_select) - raise FieldError("Cannot resolve keyword %r into field. " - "Choices are: %s" % (name, ", ".join(available))) - def setup_joins(self, names, opts, alias, can_reuse=None, allow_many=True): """ Compute the necessary table joins for the passage through the fields diff --git a/tests/queries/tests.py b/tests/queries/tests.py index 198594ea42..20c5f5d8d3 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -2164,6 +2164,13 @@ class ValuesQuerysetTests(BaseQuerysetTest): qs = qs.values_list('num', flat=True) self.assertQuerysetEqual(qs, [72], self.identity) + def test_field_error_values_list(self): + # see #23443 + with self.assertRaisesMessage(FieldError, + "Cannot resolve keyword %r into field." + " Join on 'name' not permitted." % 'foo'): + Tag.objects.values_list('name__foo') + class QuerySetSupportsPythonIdioms(TestCase):