#30796: Chaining select_related mutates original QuerySet.
-------------------------------------+-------------------------------------
Reporter: Darren | Owner: nobody
Maki |
Type: Bug | Status: new
Component: Database | Version: 2.2
layer (models, ORM) | Keywords: select_related
Severity: Normal | prefetch_related mutate queryset
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
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") 139663365718536
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")
139663366175376
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")
139663365718536
!!! 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.
--
Ticket URL: <https://code.djangoproject.com/ticket/30796>
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 view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/055.c00f5aad0b2877f8fa2beb8af9e8859e%40djangoproject.com.