#21703: `exclude` query with `F` object across relationship fails
-------------------------------------+-------------------------------------
     Reporter:  anonymous            |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  1.6
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Simon Charette):

 I confirmed this is fixed by relying on `OuterRef`

 {{{
 diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
 index 7d991b6b84..458ecaa02a 100644
 --- a/django/db/models/sql/query.py
 +++ b/django/db/models/sql/query.py
 @@ -19,7 +19,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 Col, F, Ref, SimpleCol
 +from django.db.models.expressions import (
 +    Col, F, OuterRef, Ref, SimpleCol, Subquery,
 +)
  from django.db.models.fields import Field
  from django.db.models.fields.related_lookups import MultiColSource
  from django.db.models.lookups import Lookup
 @@ -1630,6 +1632,8 @@ class Query:
          saner null handling, and is easier for the backend's optimizer to
          handle.
          """
 +        if isinstance(filter_expr[1], F):
 +            filter_expr = (filter_expr[0], OuterRef(filter_expr[1].name))
          # Generate the inner query.
          query = Query(self.model)
          query.add_filter(filter_expr)
 @@ -1662,8 +1666,10 @@ class Query:
              query.where.add(lookup, AND)
              query.external_aliases.add(alias)

 +        from django.db import models
 +        queryset = models.QuerySet(self.model, query)
          condition, needed_inner = self.build_filter(
 -            ('%s__in' % trimmed_prefix, query),
 +            ('%s__in' % trimmed_prefix, Subquery(queryset)),
              current_negated=True, branch_negated=True,
 can_reuse=can_reuse)
          if contains_louter:
              or_null_condition, _ = self.build_filter(
 }}}

 But this makes `Query` depend on `QuerySet` which we want to avoid. I have
 always thought `Subquery` wrapping of `QuerySet` instances was unnecessary
 and that `OuterRef` ought to be resolved by `Query` anyway so I'll give it
 a try.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/21703#comment:8>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/067.f728587f991c21006097a3167646294f%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to