Fixed #30796 -- Prevented select_related() from mutating a queryset on chaining.

Thanks Darren Maki for the report.
This commit is contained in:
Simon Charette 2019-09-23 15:51:43 -04:00 committed by Mariusz Felisiak
parent e8ad265ac8
commit 37f8f29377
2 changed files with 12 additions and 0 deletions

View File

@ -6,6 +6,7 @@ themselves do not have to (and could be backed by things other than SQL
databases). The abstraction barrier only works one way: this module has to know databases). The abstraction barrier only works one way: this module has to know
all about the internals of models in order to get the information it needs. all about the internals of models in order to get the information it needs.
""" """
import copy
import difflib import difflib
import functools import functools
import inspect import inspect
@ -324,6 +325,10 @@ class Query(BaseExpression):
obj._extra_select_cache = None obj._extra_select_cache = None
else: else:
obj._extra_select_cache = self._extra_select_cache.copy() obj._extra_select_cache = self._extra_select_cache.copy()
if self.select_related is not False:
# Use deepcopy because select_related stores fields in nested
# dicts.
obj.select_related = copy.deepcopy(obj.select_related)
if 'subq_aliases' in self.__dict__: if 'subq_aliases' in self.__dict__:
obj.subq_aliases = self.subq_aliases.copy() obj.subq_aliases = self.subq_aliases.copy()
obj.used_aliases = self.used_aliases.copy() obj.used_aliases = self.used_aliases.copy()

View File

@ -106,3 +106,10 @@ class TestQuery(SimpleTestCase):
self.assertIsInstance(b_isnull, RelatedIsNull) self.assertIsInstance(b_isnull, RelatedIsNull)
self.assertIsInstance(b_isnull.lhs, SimpleCol) self.assertIsInstance(b_isnull.lhs, SimpleCol)
self.assertEqual(b_isnull.lhs.target, ObjectC._meta.get_field('objectb')) self.assertEqual(b_isnull.lhs.target, ObjectC._meta.get_field('objectb'))
def test_clone_select_related(self):
query = Query(Item)
query.add_select_related(['creator'])
clone = query.clone()
clone.add_select_related(['note', 'creator__extra'])
self.assertEqual(query.select_related, {'creator': {}})