From ec50937bcbe160e658ef881021402e156beb0eaf Mon Sep 17 00:00:00 2001
From: Simon Charette <charette.s@gmail.com>
Date: Sun, 23 Apr 2017 01:05:51 -0400
Subject: [PATCH] Refs #20939 -- Removed the Query._forced_pk hack.

---
 django/db/models/fields/related_lookups.py |  2 +-
 django/db/models/lookups.py                |  3 +++
 django/db/models/query.py                  |  7 ++-----
 django/db/models/sql/query.py              | 10 +++++-----
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/django/db/models/fields/related_lookups.py b/django/db/models/fields/related_lookups.py
index 62bc92b6ff..39b8f6e941 100644
--- a/django/db/models/fields/related_lookups.py
+++ b/django/db/models/fields/related_lookups.py
@@ -81,7 +81,7 @@ class RelatedIn(In):
                     AND)
             return root_constraint.as_sql(compiler, connection)
         else:
-            if getattr(self.rhs, '_forced_pk', False):
+            if not getattr(self.rhs, 'has_select_fields', True):
                 self.rhs.clear_select_clause()
                 if (getattr(self.lhs.output_field, 'primary_key', False) and
                         self.lhs.output_field.model == self.rhs.model):
diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py
index c37fcabba4..48e68d0b8b 100644
--- a/django/db/models/lookups.py
+++ b/django/db/models/lookups.py
@@ -367,6 +367,9 @@ class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup):
             placeholder = '(' + ', '.join(sqls) + ')'
             return (placeholder, sqls_params)
         else:
+            if not getattr(self.rhs, 'has_select_fields', True):
+                self.rhs.clear_select_clause()
+                self.rhs.add_fields(['pk'])
             return super().process_rhs(compiler, connection)
 
     def get_rhs_op(self, connection, rhs):
diff --git a/django/db/models/query.py b/django/db/models/query.py
index abb95ba74a..f266e2bf22 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1100,15 +1100,12 @@ class QuerySet:
             self._known_related_objects.setdefault(field, {}).update(objects)
 
     def _prepare_as_filter_value(self):
-        if self._fields is None:
-            queryset = self.values('pk')
-            queryset.query._forced_pk = True
-        else:
+        if self._fields and len(self._fields) > 1:
             # values() queryset can only be used as nested queries
             # if they are set up to select only a single field.
             if len(self._fields) > 1:
                 raise TypeError('Cannot use multi-field values as a filter value.')
-            queryset = self._clone()
+        queryset = self._clone()
         return queryset.query.as_subquery_filter(queryset._db)
 
     def _add_hints(self, **hints):
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 6bfd454080..8c3ed06040 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -214,6 +214,10 @@ class Query:
             self._annotations = OrderedDict()
         return self._annotations
 
+    @property
+    def has_select_fields(self):
+        return bool(self.select or self.annotation_select_mask or self.extra_select_mask)
+
     def __str__(self):
         """
         Return the query as a string of SQL with the parameter values
@@ -326,7 +330,6 @@ class Query:
         if hasattr(obj, '_setup_query'):
             obj._setup_query()
         obj.context = self.context.copy()
-        obj._forced_pk = getattr(self, '_forced_pk', False)
         return obj
 
     def add_context(self, key, value):
@@ -1060,10 +1063,7 @@ class Query:
             # opts would be Author's (from the author field) and value.model
             # would be Author.objects.all() queryset's .model (Author also).
             # The field is the related field on the lhs side.
-            # If _forced_pk isn't set, this isn't a queryset query or values()
-            # or values_list() was specified by the developer in which case
-            # that choice is trusted.
-            if (getattr(value, '_forced_pk', False) and
+            if (isinstance(value, Query) and not value.has_select_fields and
                     not check_rel_lookup_compatibility(value.model, opts, field)):
                 raise ValueError(
                     'Cannot use QuerySet for "%s": Use a QuerySet for "%s".' %