Fixed #21703 -- Fixed a crash when excluding a related field with a F().

This commit is contained in:
Simon Charette 2019-03-08 02:06:34 -05:00 committed by Tim Graham
parent cbf7e71558
commit f19a4945e1
2 changed files with 12 additions and 1 deletions

View File

@ -21,7 +21,9 @@ from django.core.exceptions import (
from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections
from django.db.models.aggregates import Count from django.db.models.aggregates import Count
from django.db.models.constants import LOOKUP_SEP 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 import Field
from django.db.models.fields.related_lookups import MultiColSource from django.db.models.fields.related_lookups import MultiColSource
from django.db.models.lookups import Lookup 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 saner null handling, and is easier for the backend's optimizer to
handle. handle.
""" """
filter_lhs, filter_rhs = filter_expr
if isinstance(filter_rhs, F):
filter_expr = (filter_lhs, OuterRef(filter_rhs.name))
# Generate the inner query. # Generate the inner query.
query = Query(self.model) query = Query(self.model)
query.add_filter(filter_expr) query.add_filter(filter_expr)

View File

@ -2776,6 +2776,12 @@ class ExcludeTests(TestCase):
employment__title__in=('Engineer', 'Developer')).distinct().order_by('name') employment__title__in=('Engineer', 'Developer')).distinct().order_by('name')
self.assertSequenceEqual(alex_nontech_employers, [google, intel, microsoft]) 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): class ExcludeTest17600(TestCase):
""" """