Fixed #12049 - LazyObject-wrapped User breaks queries in template tags
Thanks to chipx86 for the report and patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11634 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
cb7a3262b5
commit
22be3d7612
|
@ -297,6 +297,11 @@ class SimpleLazyObject(LazyObject):
|
||||||
def __init__(self, func):
|
def __init__(self, func):
|
||||||
"""
|
"""
|
||||||
Pass in a callable that returns the object to be wrapped.
|
Pass in a callable that returns the object to be wrapped.
|
||||||
|
|
||||||
|
If copies are made of the resulting SimpleLazyObject, which can happen
|
||||||
|
in various circumstances within Django, then you must ensure that the
|
||||||
|
callable can be safely run more than once and will return the same
|
||||||
|
value.
|
||||||
"""
|
"""
|
||||||
self.__dict__['_setupfunc'] = func
|
self.__dict__['_setupfunc'] = func
|
||||||
# For some reason, we have to inline LazyObject.__init__ here to avoid
|
# For some reason, we have to inline LazyObject.__init__ here to avoid
|
||||||
|
@ -307,5 +312,14 @@ class SimpleLazyObject(LazyObject):
|
||||||
if self._wrapped is None: self._setup()
|
if self._wrapped is None: self._setup()
|
||||||
return str(self._wrapped)
|
return str(self._wrapped)
|
||||||
|
|
||||||
|
def __deepcopy__(self, memo):
|
||||||
|
if self._wrapped is None:
|
||||||
|
result = self.__class__(self._setupfunc)
|
||||||
|
memo[id(self)] = result
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
import copy
|
||||||
|
return copy.deepcopy(self._wrapped, memo)
|
||||||
|
|
||||||
def _setup(self):
|
def _setup(self):
|
||||||
self._wrapped = self._setupfunc()
|
self._wrapped = self._setupfunc()
|
||||||
|
|
|
@ -3,6 +3,8 @@ Tests for Django's bundled context processors.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
|
from django.db.models import Q
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.template import Template
|
from django.template import Template
|
||||||
|
|
||||||
|
@ -81,3 +83,20 @@ class AuthContextProcessorTests(TestCase):
|
||||||
self.assertContains(response, "username: super")
|
self.assertContains(response, "username: super")
|
||||||
# bug #12037 is tested by the {% url %} in the template:
|
# bug #12037 is tested by the {% url %} in the template:
|
||||||
self.assertContains(response, "url: /userpage/super/")
|
self.assertContains(response, "url: /userpage/super/")
|
||||||
|
|
||||||
|
# See if this object can be used for queries where a Q() comparing
|
||||||
|
# a user can be used with another Q() (in an AND or OR fashion).
|
||||||
|
# This simulates what a template tag might do with the user from the
|
||||||
|
# context. Note that we don't need to execute a query, just build it.
|
||||||
|
#
|
||||||
|
# The failure case (bug #12049) on Python 2.4 with a LazyObject-wrapped
|
||||||
|
# User is a fatal TypeError: "function() takes at least 2 arguments
|
||||||
|
# (0 given)" deep inside deepcopy().
|
||||||
|
#
|
||||||
|
# Python 2.5 and 2.6 succeeded, but logged internally caught exception
|
||||||
|
# spew:
|
||||||
|
#
|
||||||
|
# Exception RuntimeError: 'maximum recursion depth exceeded while
|
||||||
|
# calling a Python object' in <type 'exceptions.AttributeError'>
|
||||||
|
# ignored"
|
||||||
|
query = Q(user=response.context['user']) & Q(someflag=True)
|
||||||
|
|
Loading…
Reference in New Issue