#17439: prefetch_related issues extra queries for optional OneToOneFields
----------------------------------------------+--------------------
     Reporter:  gwahl@…                       |      Owner:  nobody
         Type:  Bug                           |     Status:  new
    Component:  Database layer (models, ORM)  |    Version:  SVN
     Severity:  Normal                        |   Keywords:
 Triage Stage:  Unreviewed                    |  Has patch:  0
Easy pickings:  0                             |      UI/UX:  0
----------------------------------------------+--------------------
 Given these models:

 {{{#!python
 class ModelA(models.Model):
     pass

 class ModelB(models.Model):
     a = models.OneToOneField(ModelA, related_name='b')
 }}}

 I expect that after doing `ModelA.objects.prefetch_related('b')`, the `b`
 attribute of all the results can be accessed without causing another
 query. This is not the case:

 {{{
 >>> from app.models import *
 >>> a = ModelA.objects.all()[0]
 SELECT "app_modela"."id"
 FROM "app_modela" LIMIT 1

 >>> a.b  # should do a query, prefetch_related was not used
 SELECT "app_modelb"."id",
        "app_modelb"."a_id"
 FROM "app_modelb"
 WHERE "app_modelb"."a_id" = 1

 Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "/srv/python-
 environments/egg/src/django/django/db/models/fields/related.py", line 255,
 in __get__
     rel_obj = self.get_query_set(instance=instance).get(**params)
   File "/srv/python-
 environments/egg/src/django/django/db/models/query.py", line 361, in get
     % self.model._meta.object_name)
 DoesNotExist: ModelB matching query does not exist.
 ## it did another query, and raised DoesNotExist, just like expected.
 >>> a = ModelA.objects.all().prefetch_related('b')[0]
 SELECT "app_modela"."id"
 FROM "app_modela" LIMIT 1

 SELECT "app_modelb"."id",
        "app_modelb"."a_id"
 FROM "app_modelb"

 >>> a.b  # should not do a query, we already got all the `b`s
 SELECT "app_modelb"."id",
        "app_modelb"."a_id"
 FROM "app_modelb"
 WHERE "app_modelb"."a_id" = 1

 Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "/srv/python-
 environments/egg/src/django/django/db/models/fields/related.py", line 255,
 in __get__
     rel_obj = self.get_query_set(instance=instance).get(**params)
   File "/srv/python-
 environments/egg/src/django/django/db/models/query.py", line 361, in get
     % self.model._meta.object_name)
 DoesNotExist: ModelB matching query does not exist.
 ## Another query was issued even though we know it can not return any
 results
 >>>
 }}}

 Any possible `b` object was already fetched by `prefetch_related`, but
 accessing the property causes another query anyway. Note that this is only
 the
 case when `a` does not have a `b` object, the extra query does not happen
 if
 there was a `b` fetched by `prefetch_related`.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/17439>
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 post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to