#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 django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.