I've run into an infinite loop under some circumstances with raw()
queries and overridden __init__ methods in models.  Here's the
smallest test case I could come up with that exhibits the problem:


from django.db import models

class ModelWithSlug(models.Model):
  slug = models.SlugField(unique = True, max_length = 100)

  def __init__(self, *args, **kwargs):
    super(ModelWithSlug, self).__init__(*args, **kwargs)

    print getattr(self, self.slug_field) # <-----------------

  def save(self, **kwargs):
    self.slug = self.name
    super(ModelWithSlug, self).save(**kwargs)

  class Meta:
    abstract = True


class Package(models.Model):
  name = models.CharField(max_length = 100, null = False, blank =
False)


class Album(ModelWithSlug):
  name = models.CharField(max_length = 100)
  is_singles = models.BooleanField(default = False)
  slug_field = "name"
  package = models.ForeignKey(Package, related_name='albums')

  def __init__(self, *args, **kwargs):
    super(Album, self).__init__(*args, **kwargs)
    print self.package # <-----------------


def test():
  p, _ = Package.objects.get_or_create(name = "p")
  a, _ = Album.objects.get_or_create(name = "hello", package = p)

  albums = Album.objects.raw("SELECT id, name, package_id FROM
managerfail2_album")
  return list(albums)[0].slug


Now, from what I understand, when the test() method is executed, the
__init__ of ModelWithSlug is called, which tries to retrieve the slug
field, which wasn't part of the raw() query, so django tries to
retrieve it.  But then looking further down the stack, the "print
self.package" fails, and the whole process loops infinitely.  If I
comment out *either* of the print statements, everything is happy.  If
I add "slug" to the raw() query, everything is happy.  Here's the
first couple of loops of the traceback:


/home/amagee/tmp/managerfail2/models.pyc in test()
     36   a, _ = Album.objects.get_or_create(name = "hello", package =
p)
     37
     38   albums = Album.objects.raw("SELECT id, name, package_id FROM
managerfail2_album")
---> 39   return list(albums)[0].slug
     40

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query_utils.pyc in __get__(self, instance, owner)
    100             val = getattr(
    101
cls._base_manager.filter(pk=instance.pk).only(name).using(
--> 102                     instance._state.db).get(),
    103                 self.field_name
    104             )

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in get(self, *args, **kwargs)
    342         if self.query.can_filter():
    343             clone = clone.order_by()
--> 344         num = len(clone)
    345         if num == 1:
    346             return clone._result_cache[0]

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in __len__(self)
     80                 self._result_cache = list(self._iter)
     81             else:
---> 82                 self._result_cache = list(self.iterator())
     83         elif self._iter:
     84             self._result_cache.extend(self._iter)

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in iterator(self)
    281                     row_data =
row[index_start:aggregate_start]
    282                     pk_val = row_data[pk_idx]
--> 283                     obj = model_cls(**dict(zip(init_list,
row_data)))
    284                 else:
    285                     # Omit aggregates in object creation.


/home/amagee/tmp/managerfail2/models.pyc in __init__(self, *args,
**kwargs)
     28
     29   def __init__(self, *args, **kwargs):
---> 30     super(Album, self).__init__(*args, **kwargs)
     31     print self.package # <-----------------
     32

/home/amagee/tmp/managerfail2/models.pyc in __init__(self, *args,
**kwargs)
      7     super(ModelWithSlug, self).__init__(*args, **kwargs)
      8
----> 9     print getattr(self, self.slug_field) # <-----------------
     10
     11   def save(self, **kwargs):

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query_utils.pyc in __get__(self, instance, owner)
    100             val = getattr(
    101
cls._base_manager.filter(pk=instance.pk).only(name).using(
--> 102                     instance._state.db).get(),
    103                 self.field_name
    104             )

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in get(self, *args, **kwargs)
    342         if self.query.can_filter():
    343             clone = clone.order_by()
--> 344         num = len(clone)
    345         if num == 1:
    346             return clone._result_cache[0]

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in __len__(self)
     80                 self._result_cache = list(self._iter)
     81             else:
---> 82                 self._result_cache = list(self.iterator())
     83         elif self._iter:
     84             self._result_cache.extend(self._iter)

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in iterator(self)
    281                     row_data =
row[index_start:aggregate_start]
    282                     pk_val = row_data[pk_idx]
--> 283                     obj = model_cls(**dict(zip(init_list,
row_data)))
    284                 else:
    285                     # Omit aggregates in object creation.


/home/amagee/tmp/managerfail2/models.pyc in __init__(self, *args,
**kwargs)
     29   def __init__(self, *args, **kwargs):
     30     super(Album, self).__init__(*args, **kwargs)
---> 31     print self.package # <-----------------
     32
     33

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
fields/related.pyc in __get__(self, instance, instance_type)
    294             return getattr(instance, cache_name)
    295         except AttributeError:
--> 296             val = getattr(instance, self.field.attname)
    297             if val is None:
    298                 # If NULL is an allowed value, return it.


/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query_utils.pyc in __get__(self, instance, owner)
    100             val = getattr(
    101
cls._base_manager.filter(pk=instance.pk).only(name).using(
--> 102                     instance._state.db).get(),
    103                 self.field_name
    104             )

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in get(self, *args, **kwargs)
    342         if self.query.can_filter():
    343             clone = clone.order_by()
--> 344         num = len(clone)
    345         if num == 1:
    346             return clone._result_cache[0]

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in __len__(self)
     80                 self._result_cache = list(self._iter)
     81             else:
---> 82                 self._result_cache = list(self.iterator())
     83         elif self._iter:
     84             self._result_cache.extend(self._iter)

/home/amagee/playfi_env/lib/python2.6/site-packages/django/db/models/
query.pyc in iterator(self)
    281                     row_data =
row[index_start:aggregate_start]
    282                     pk_val = row_data[pk_idx]
--> 283                     obj = model_cls(**dict(zip(init_list,
row_data)))
    284                 else:
    285                     # Omit aggregates in object creation.


/home/amagee/tmp/managerfail2/models.pyc in __init__(self, *args,
**kwargs)
     28
     29   def __init__(self, *args, **kwargs):
---> 30     super(Album, self).__init__(*args, **kwargs)
     31     print self.package # <-----------------
     32

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to