﻿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
18090	`prefetch_related` selects entire table when reverse traversing a `OneToOneField`	Aymeric Augustin	nobody	"This is best demonstrated with an example:

'''myapp/models.py'''

{{{
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=10)

class Group(models.Model):
    users = models.ManyToManyField(User)

class GroupExtra(models.Model):
    group = models.OneToOneField(Group)
}}}

'''./manage.py shell'''

{{{

# Let's create 10 users, 5 groups + group_extras.

>>> from myapp.models import *
>>> users = [User.objects.create(name='user %d' % i) for i in range(10)]
>>> groups = [Group.objects.create() for i in range(5)]
>>> for i in range(5):
...     groups[i].users = users[i:i + 5]
... 
>>> group_extras = [GroupExtra.objects.create(group=groups[i]) for i in range(5)]

# Load an user with his groups and group_extras.

>>> from pprint import pprint
>>> from django.db import connection
>>> connection.queries = []
>>> user = User.objects.prefetch_related('group_set__groupextra').get(name='user 3')
>>> pprint(connection.queries)
[{'sql': u'SELECT ""myapp_user"".""id"", ""myapp_user"".""name"" FROM ""myapp_user"" WHERE ""myapp_user"".""name"" = user 3 ',
  'time': '0.000'},
 {'sql': u'SELECT (""myapp_group_users"".""user_id"") AS ""_prefetch_related_val"", ""myapp_group"".""id"" FROM ""myapp_group"" INNER JOIN ""myapp_group_users"" ON (""myapp_group"".""id"" = ""myapp_group_users"".""group_id"") WHERE ""myapp_group_users"".""user_id"" IN (4)',
  'time': '0.000'},
 {'sql': u'SELECT ""myapp_groupextra"".""id"", ""myapp_groupextra"".""group_id"" FROM ""myapp_groupextra""',
  'time': '0.000'}]

# The last query unnecessarily loaded the entire `myapp_groupextra` table.

# But prefetch_related worked as expected: the following code doesn't trigger another query

>>> connection.queries = []
>>> for group in user.group_set.all():
...     print group.pk, group.groupextra.pk
... 
1 1
2 2
3 3
4 4
>>> pprint(connection.queries)
[]
}}}
"	Bug	closed	Database layer (models, ORM)	1.4	Normal	fixed			Unreviewed	0	0	0	0	0	0
