#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.

Reply via email to