Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#15790 closed Bug (fixed)

only() broken for proxy models

Reported by: michal.modzelewski@… Owned by: Michał Modzelewski
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords: proxy only
Cc: michal.modzelewski@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Usage of deferred fields with proxy models is broken.

For example when using the following models

class Item(models.Model):
    name = models.CharField(max_length=15)
    text = models.TextField(default="xyzzy")
    value = models.IntegerField()
    other_value = models.IntegerField(default=0)

class Proxy(Item):
    class Meta:
        proxy = True

we create an item with

>>> proxy = Proxy.objects.create(name="proxy", value=42)

Now depending on whether we call only() with 'id' or not we get different behaviour.
Without 'id' we get an endless loop.

>>> deferredproxy = Proxy.objects.only('value').get(
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/michal/.local/lib/python2.7/site-packages/django/db/models/", line 100, in __get__
  File "/home/michal/.local/lib/python2.7/site-packages/django/db/models/", line 426, in _get_pk_val
    return getattr(self,
  File "/home/michal/.local/lib/python2.7/site-packages/django/db/models/", line 100, in __get__
  File "/home/michal/.local/lib/python2.7/site-packages/django/db/models/", line 426, in _get_pk_val
    return getattr(self,
RuntimeError: maximum recursion depth exceeded

With 'id' we get the wrong value when accessing a deferred field.

>>> deferredproxy = Proxy.objects.only('id', 'value').get(

This value happens to be the object id.


Comparing the objects returned with examples using the base model.

>>> Proxy.objects.only('other_value').get(
{'_state': <django.db.models.base.ModelState object at 0x89bd58c>, 'other_value': 3}
>>> Item.objects.only('other_value').get(
{'_state': <django.db.models.base.ModelState object at 0x89bd80c>, 'id': 3, 'other_value': 0}
>>> Proxy.objects.only('name', 'text', 'value', 'other_value').get(
{'text': u'proxy', '_state': <django.db.models.base.ModelState object at 0x89bda8c>, 'name': 3, 'value': u'xyzzy', 'other_value': 42}
>>> Item.objects.only('name', 'text', 'value', 'other_value').get(
{'name': u'proxy', 'text': u'xyzzy', '_state': <django.db.models.base.ModelState object at 0x89bdcec>, 'value': 42, 'other_value': 0, 'id': 3}

'id' is missing from the __dict__ for the proxy models, and all the values are shifted.

Attachments (2)

15790_only_broken_for_proxy_models.diff (2.6 KB) - added by michal.modzelewski@… 8 years ago.
Patch for this bug, with regression tests
15790_only_broken_for_proxy_models.2.diff (2.7 KB) - added by Michał Modzelewski 8 years ago.
Updated patch for trunk

Download all attachments as: .zip

Change History (9)

Changed 8 years ago by michal.modzelewski@…

Patch for this bug, with regression tests

comment:1 Changed 8 years ago by michal.modzelewski@…

Has patch: set
milestone: 1.3
Triage Stage: UnreviewedAccepted

comment:2 Changed 8 years ago by Luke Plant

Severity: Release blockerNormal

I don't think this is a release blocker, as it is not a regression, or a serious bug with a new feature in 1.3 that would have blocked it.

comment:3 Changed 8 years ago by Michał Modzelewski <michal.modzelewski@…>

Yes, i originally thought that this could result in an unintentional loss of data if you saved such a broken model instance, but since the pk value is missing from the __dict__ saving will just create a new record in the database.

comment:4 Changed 8 years ago by Michał Modzelewski

Easy pickings: unset
milestone: 1.31.4
Owner: changed from nobody to Michał Modzelewski
Status: newassigned

Changed 8 years ago by Michał Modzelewski

Updated patch for trunk

comment:5 Changed 8 years ago by kgibula

Triage Stage: AcceptedReady for checkin

Patch applies cleanly and the described issue is fixed.

comment:6 Changed 8 years ago by Ramiro Morales

Resolution: fixed
Status: assignedclosed

In [16228]:

Fixed #15790 -- Fixed QuerySet only() and defer() methods behavior with proxy models. Thanks Michal Modzelewzki for the report and patch.

comment:7 Changed 7 years ago by Jacob

milestone: 1.4

Milestone 1.4 deleted

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