#15062: r14389 breaks getattr on Manager subclasses
------------------------------------------+---------------------------------
Reporter: clelland | Owner: nobody
Status: new | Milestone: 1.3
Component: Database layer (models, ORM) | Version: SVN
Keywords: | Stage: Unreviewed
Has_patch: 0 |
------------------------------------------+---------------------------------
I've been using Simon Willison's [http://djangosnippets.org/snippets/734/
QuerySetManager] pattern for a while now, and since upgrading to Django
1.2.4, it has been breaking when I try to call a method on a
!RelatedManager constructed from it.
There was a change in r14389 (r14390 in the 1.2.X branch) which causes
this code to break -- where there was a simple delegation before from the
!RelatedManager to the !QuerySetManager to the model, there now appears to
be an infinite recursion, with the !RelatedManager and !QuerySetManager
trying to call each other's get_query_set methods.
!QuerySetManager is just a simple subclass of `django.db.models.Manager`,
which overrides `__getattr__` to proxy custom method calls on the manager
to a class attached to the underlying model.
The simplest test case I can get to reproduce this problem looks like
this:
{{{
from django.db import models
from django.contrib.auth.models import User
from helpers import QuerySetManager
class TestModel(models.Model):
user = models.ForeignKey(User)
string = models.CharField(max_length=64, null=True, blank=True)
objects = QuerySetManager()
class QuerySet(models.query.QuerySet):
pass
}}}
Using it gives a traceback like this:
{{{
>>> user = User.objects.get(username='testuser')
>>> user.testmodel_set.create(string="test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
user.testmodel_set.create(string="test")
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/fields/related.py", line 423, in create
return super(RelatedManager, self.db_manager(db)).create(**kwargs)
File "/Users/ian/.virtualenvs/egather/lib/python2.6/site-
packages/django/db/models/manager.py", line 138, in create
return self.get_query_set().create(**kwargs)
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/fields/related.py", line 410, in get_query_set
return
superclass.get_query_set(self).using(db).filter(**(self.core_filters))
File "/Users/ian/Code/Tests/related_test/test_app/models.py", line 17, in
__getattr__
return getattr(self.get_query_set(), attr, *args)
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/fields/related.py", line 410, in get_query_set
return
superclass.get_query_set(self).using(db).filter(**(self.core_filters))
File "/Users/ian/Code/Tests/related_test/test_app/models.py", line 17, in
__getattr__
return getattr(self.get_query_set(), attr, *args)
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/fields/related.py", line 410, in get_query_set
return
superclass.get_query_set(self).using(db).filter(**(self.core_filters))
File "/Users/ian/Code/Tests/related_test/test_app/models.py", line 17, in
__getattr__
return getattr(self.get_query_set(), attr, *args)
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/fields/related.py", line 410, in get_query_set
return
superclass.get_query_set(self).using(db).filter(**(self.core_filters))
File "/Users/ian/Code/Tests/related_test/test_app/models.py", line 17, in
__getattr__
return getattr(self.get_query_set(), attr, *args)
...
Lots snipped
...
File "/Users/ian/.virtualenvs/egather/lib/python2.6/site-
packages/django/db/models/fields/related.py", line 410, in get_query_set
return
superclass.get_query_set(self).using(db).filter(**(self.core_filters))
File "/Users/ian/Code/Tests/related_test/test_app/models.py", line 14, in
get_query_set
return self.model.QuerySet(self.model)
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/query.py", line 33, in __init__
self.query = query or sql.Query(self.model)
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/db/models/sql/query.py", line 138, in __init__
self.aggregates = SortedDict() # Maps alias -> SQL aggregate function
File "/Users/ian/.virtualenvs/testcode/lib/python2.6/site-
packages/django/utils/datastructures.py", line 97, in __init__
super(SortedDict, self).__init__(data)
RuntimeError: maximum recursion depth exceeded while calling a Python
object
}}}
--
Ticket URL: <http://code.djangoproject.com/ticket/15062>
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.