From f19a4945e1191e1696f1ad8e6cdc6f939c702728 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Fri, 8 Mar 2019 02:06:34 -0500 Subject: [PATCH] Fixed #21703 -- Fixed a crash when excluding a related field with a F(). --- django/db/models/sql/query.py | 7 ++++++- tests/queries/tests.py | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index eac61106c6..4f2fe5acb5 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -21,7 +21,9 @@ from django.core.exceptions import ( from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections from django.db.models.aggregates import Count from django.db.models.constants import LOOKUP_SEP -from django.db.models.expressions import BaseExpression, Col, F, Ref, SimpleCol +from django.db.models.expressions import ( + BaseExpression, Col, F, OuterRef, Ref, SimpleCol, +) from django.db.models.fields import Field from django.db.models.fields.related_lookups import MultiColSource from django.db.models.lookups import Lookup @@ -1639,6 +1641,9 @@ class Query(BaseExpression): saner null handling, and is easier for the backend's optimizer to handle. """ + filter_lhs, filter_rhs = filter_expr + if isinstance(filter_rhs, F): + filter_expr = (filter_lhs, OuterRef(filter_rhs.name)) # Generate the inner query. query = Query(self.model) query.add_filter(filter_expr) diff --git a/tests/queries/tests.py b/tests/queries/tests.py index 76f42fee73..373a0e224a 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -2776,6 +2776,12 @@ class ExcludeTests(TestCase): employment__title__in=('Engineer', 'Developer')).distinct().order_by('name') self.assertSequenceEqual(alex_nontech_employers, [google, intel, microsoft]) + def test_exclude_reverse_fk_field_ref(self): + tag = Tag.objects.create() + Note.objects.create(tag=tag, note='note') + annotation = Annotation.objects.create(name='annotation', tag=tag) + self.assertEqual(Annotation.objects.exclude(tag__note__note=F('name')).get(), annotation) + class ExcludeTest17600(TestCase): """