#22508 closed Bug (fixed)
select_related on a foreign related object fails to load fields on original object
| Reported by: | Malcolm Box | Owned by: | Aymeric Augustin |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.6 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Consider these models:
class Show(models.Model):
pass
class Poll(models.Model):
event = models.ForeignKey('Event')
class Event(models.Model)
show = models.ForeignKey(Show)
The following code fails to load the poll.event.show attribute:
In [3]: event = Event.objects.all()[2]
In [4]: poll = event.poll_set.select_related('event', 'event__show').all()[0]
In [5]: hasattr(poll.event, '_show_cache')
Out[5]: False
For comparison, in 1.4 the same code produces:
In [12]: event = Event.objects.all()[2]
In [13]: poll = event.poll_set.select_related('event', 'event__show').all()[0]
In [14]: hasattr(poll.event, '_show_cache')
Out[14]: True
The bug appears to be in the known_objects code around line 247 in db/models/query.py which looks like it will overwrite the poll.event attribute that was just retrieved from the DB (via select_related) and replaces it with the parent model, which in this case doesn't have the show attribute loaded.
Since the ORM was explicitly instructed to load the Event model in the call, it shouldn't then replace the poll.event attribute with the previously-known parent model.
Change History (12)
comment:1 by , 12 years ago
| Type: | Uncategorized → Bug |
|---|
comment:2 by , 12 years ago
comment:3 by , 12 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
I knew I shouldn't have touched this code...
comment:4 by , 12 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:5 by , 11 years ago
| Has patch: | set |
|---|
I've sent a pull request: https://github.com/django/django/pull/2646. The fix is straightforward.
Since this can cause silent performance regressions, I would suggest backporting f574220f0988f3aa1aca4f133887fbde0e5a6f10 to 1.7, 1.6 and 1.5.
QuerySet.iterator is growing a bit complex and might benefit from a refactoring.
comment:6 by , 11 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Looks good, also for backporting, with a slight reserve about 1.5 being in security/data-loss bug fix only.
comment:7 by , 11 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Bisected to 1e6c3368f2517f32b0651d68277ea8c9ef81d9b2