Opened 7 years ago

Closed 7 years ago

#28375 closed Bug (fixed)

QuerySet.prefetch_related() crashes with KeyError if model uses to_field and string primary key

Reported by: Maks Y Owned by: Paulo
Component: Database layer (models, ORM) Version: 1.11
Severity: Normal Keywords: prefetch_related string primary key.
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The issue:
prefetch_related failed if prefetching by char primary key.

Django version 1.11.3
Python 2.7

reproducible steps:
1) django-admin startproject pk_string

2) cd pk_string

3) django-admin startapp users

4) update users.models

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.

class User(models.Model):
    email = models.CharField(max_length=255, unique=True)

class UserData(models.Model):
    email = models.OneToOneField(User, to_field='email', primary_key=True)
    note = models.CharField(max_length=255);

5) install app pk_string.settings

...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
]
...

6) ./manage.py makemigrations
7) ./manage.py migrate
8) ./manage.py shell

from users.models import User, UserData
User.objects.create(email = '111111')
User.objects.create(email = '222222')
User.objects.create(email = '333333')
User.objects.create(email = '444444')

users = User.objects.all().prefetch_related('userdata')
users[0]
>>> "<User: User object>" 

UserData.objects.create(email=users[0] , note = '111')
UserData.objects.create(email=users[2] , note = '222')
UserData.objects.create(email=users[3] , note = '333')
users = User.objects.all().prefetch_related('userdata')

>>> users[0]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 289, in __getitem__
    return list(qs)[0]
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 250, in __iter__
    self._fetch_all()
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 1120, in _fetch_all
    self._prefetch_related_objects()
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 675, in _prefetch_related_objects
    prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups)
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 1469, in prefetch_related_objects
    obj_list, additional_lookups = prefetch_one_level(obj_list, prefetcher, lookup, level)
  File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 1582, in prefetch_one_level
    prefetcher.get_prefetch_queryset(instances, lookup.get_current_queryset(level)))
  File "/usr/local/lib/python2.7/site-packages/django/db/models/fields/related_descriptors.py", line 362, in get_prefetch_queryset
    instance = instances_dict[rel_obj_attr(rel_obj)]
KeyError: u'111111'

Attachments (1)

pk_string.tar.gz (13.2 KB ) - added by Maks Y 7 years ago.
Project example source code. So you could skip all steps and begin from the last step to reproduce the issue.

Download all attachments as: .zip

Change History (7)

by Maks Y, 7 years ago

Attachment: pk_string.tar.gz added

Project example source code. So you could skip all steps and begin from the last step to reproduce the issue.

comment:1 by Tim Graham, 7 years ago

Summary: prefetch_related bug with string primary key.QuerySet.prefetch_related() crashes with KeyError if model uses to_field and string primary key
Triage Stage: UnreviewedAccepted

comment:2 by Paulo, 7 years ago

Owner: changed from nobody to Paulo
Status: newassigned

comment:3 by Paulo, 7 years ago

Hello Tim,
Will a fix for this be backported to 1.11?
If that is the case, then I can make sure to base if off of current master instead of https://github.com/django/django/pull/6721

comment:4 by Tim Graham, 7 years ago

A fix could be backported if the patch is simple and the risk of introducing a regression seems low.

comment:6 by Tim Graham <timograham@…>, 7 years ago

Resolution: fixed
Status: assignedclosed

In fea9cb4:

Fixed #28375 -- Fixed KeyError crash on reverse prefetch of a model with OneToOneField primary key to a non-pk field.

Note: See TracTickets for help on using tickets.
Back to Top