﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
30796	Chaining select_related mutates original QuerySet.	Darren Maki	nobody	"When creating a new QuerySet from an existing QuerySet that has had 'select_related' applied, if you apply another 'select_related' to the new QuerySet it will mutate the original QuerySet to also have the extra 'select_related'.

'''models.py'''

{{{
from django.db import models

class ModelA(models.Model):
    pass

class ModelB(models.Model):
    pass

class ModelC(models.Model):
    model_a = models.ForeignKey('foobar.ModelA', on_delete=models.CASCADE)
    model_b = models.ForeignKey('foobar.ModelB', on_delete=models.CASCADE)
}}}

'''test.py'''

{{{
query_1 = ModelC.objects.select_related('model_a')
print('QUERY 1:', str(query_1.query))

query_2 = query_1.select_related('model_b')
print('QUERY 2:', str(query_2.query))

print('QUERY 1:', str(query_1.query))

if str(query_1.query) == str(query_2.query):
    print('\n!!! The two queries are the same !!!\n')
}}}

'''output'''

{{{
QUERY 1: SELECT ""foobar_modelc"".""id"", ""foobar_modelc"".""model_a_id"", ""foobar_modelc"".""model_b_id"", ""foobar_modela"".""id"" FROM ""foobar_modelc"" INNER JOIN ""foobar_modela"" ON (""foobar_modelc"".""model_a_id"" = ""foobar_modela"".""id"")
QUERY 2: SELECT ""foobar_modelc"".""id"", ""foobar_modelc"".""model_a_id"", ""foobar_modelc"".""model_b_id"", ""foobar_modela"".""id"", ""foobar_modelb"".""id"" FROM ""foobar_modelc"" INNER JOIN ""foobar_modela"" ON (""foobar_modelc"".""model_a_id"" = ""foobar_modela"".""id"") INNER JOIN ""foobar_modelb"" ON (""foobar_modelc"".""model_b_id"" = ""foobar_modelb"".""id"")
QUERY 1: SELECT ""foobar_modelc"".""id"", ""foobar_modelc"".""model_a_id"", ""foobar_modelc"".""model_b_id"", ""foobar_modela"".""id"", ""foobar_modelb"".""id"" FROM ""foobar_modelc"" INNER JOIN ""foobar_modela"" ON (""foobar_modelc"".""model_a_id"" = ""foobar_modela"".""id"") INNER JOIN ""foobar_modelb"" ON (""foobar_modelc"".""model_b_id"" = ""foobar_modelb"".""id"")

!!! The two queries are the same !!!

}}}

The expectation is that the original QuerySet is not mutated, and the two queries are different. This behavior also happens with 'prefetch_related'.

Since the QuerySet methods call 'self._clone()', and state that they return 'a new QuerySet instance', this behavior does not seem correct.
"	Bug	new	Database layer (models, ORM)	2.2	Normal		select_related prefetch_related mutate queryset		Unreviewed	0	0	0	0	0	0
