#15790: only() broken for proxy models
-----------------------------+---------------------------------------------
 Reporter:                   |         Owner:  nobody
  michal.modzelewski@…       |        Status:  new
     Type:  Bug              |     Component:  Database layer (models, ORM)
Milestone:                   |      Severity:  Release blocker
  Version:  SVN              |  Triage Stage:  Unreviewed
 Keywords:  proxy only       |
Has patch:  0                |
-----------------------------+---------------------------------------------
 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(pk=proxy.pk)
 >>> deferredproxy.name
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
     deferredproxy.name
   File "/home/michal/.local/lib/python2.7/site-
 packages/django/db/models/query_utils.py", line 100, in __get__
     cls._base_manager.filter(pk=instance.pk).only(name).using(
   File "/home/michal/.local/lib/python2.7/site-
 packages/django/db/models/base.py", line 426, in _get_pk_val
     return getattr(self, meta.pk.attname)
   File "/home/michal/.local/lib/python2.7/site-
 packages/django/db/models/query_utils.py", line 100, in __get__
     cls._base_manager.filter(pk=instance.pk).only(name).using(
 ...
   File "/home/michal/.local/lib/python2.7/site-
 packages/django/db/models/base.py", line 426, in _get_pk_val
     return getattr(self, meta.pk.attname)
 RuntimeError: maximum recursion depth exceeded
 }}}
 With 'id' we get the wrong value when accessing a deferred field.
 {{{
 >>> deferredproxy = Proxy.objects.only('id', 'value').get(pk=proxy.pk)
 >>> deferredproxy.name
 3
 }}}
 This value happens to be the object id.
 {{{
 >>> proxy.id
 3
 }}}

 Comparing the objects returned with examples using the base model.
 {{{
 >>> Proxy.objects.only('other_value').get(pk=proxy.pk).__dict__
 {'_state': <django.db.models.base.ModelState object at 0x89bd58c>,
 'other_value': 3}
 >>> Item.objects.only('other_value').get(pk=proxy.pk).__dict__
 {'_state': <django.db.models.base.ModelState object at 0x89bd80c>, 'id':
 3, 'other_value': 0}
 >>> Proxy.objects.only('name', 'text', 'value',
 'other_value').get(pk=proxy.pk).__dict__
 {'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(pk=proxy.pk).__dict__
 {'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.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/15790>
Django <http://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 [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to