Ticket #6552: 6552.diff
File 6552.diff, 9.2 KB (added by , 15 years ago) |
---|
-
django/core/context_processors.py
diff -r 6490bd644de2 django/core/context_processors.py
a b 8 8 """ 9 9 10 10 from django.conf import settings 11 from django.template.utils import ContextLazyObject 11 12 12 13 def auth(request): 13 14 """ … … 17 18 If there is no 'user' attribute in the request, uses AnonymousUser (from 18 19 django.contrib.auth). 19 20 """ 20 if hasattr(request, 'user'): 21 user = request.user 22 else: 23 from django.contrib.auth.models import AnonymousUser 24 user = AnonymousUser() 21 # If we access request.user, request.session is accessed, which results in 22 # 'Vary: Cookie' being sent in every request that uses this context 23 # processor, which can easily be every request on a site if 24 # TEMPLATE_CONTEXT_PROCESSORS has this context processor added. This kills 25 # the ability to cache. So, we carefully ensure these attributes are lazy. 26 # We don't use django.utils.functional.lazy(), because that requires knowing 27 # the class of the object we want to proxy, which could break with custom 28 # auth backends. LazyObject is a less complete but more flexible solution 29 # that is good enough for wrapper 'User'. Also, lazy doesn't seem to work 30 # fully with PermWrapper, so we have modified that to allow laziness. 31 def get_user(): 32 if hasattr(request, 'user'): 33 return request.user 34 else: 35 from django.contrib.auth.models import AnonymousUser 36 return AnonymousUser() 37 38 def messages(): 39 for m in get_user().get_and_delete_messages(): 40 yield m 41 25 42 return { 26 'user': user,27 'messages': user.get_and_delete_messages(),28 'perms': PermWrapper(user),43 'user': ContextLazyObject(get_user), 44 'messages': messages(), 45 'perms': PermWrapper(get_user), 29 46 } 30 47 31 48 def debug(request): … … 75 92 76 93 class PermWrapper(object): 77 94 def __init__(self, user): 78 self.user = user 95 self._user = user 96 97 def user(self): 98 # Allow callable for laziness 99 if callable(self._user): 100 self._user = self._user() 101 return self._user 102 user = property(user) 79 103 80 104 def __getitem__(self, module_name): 81 105 return PermLookupDict(self.user, module_name) 82 106 83 107 def __iter__(self): 84 108 # I am large, I contain multitudes. 85 109 raise TypeError("PermWrapper is not iterable.") -
new file django/template/utils.py
diff -r 6490bd644de2 django/template/utils.py
- + 1 from django.utils.functional import LazyObject 2 3 class ContextLazyObject(LazyObject): 4 """ 5 A lazy object initialised from any function, useful for lazily 6 adding things to the Context. 7 8 Works best for compound objects of unknown type where you are only 9 interested in the attributes, and won't need things like str(obj). For 10 simple objects of known type, use django.utils.functional.lazy 11 12 For sequences, use a generator instead. 13 """ 14 def __init__(self, func): 15 """ 16 Pass in a callable that returns the actual value to be used 17 """ 18 self.__dict__['_setupfunc'] = func 19 # For some reason, we have to inline LazyObject.__init__ here to avoid 20 # recursion 21 self._wrapped = None 22 23 def _setup(self): 24 self._wrapped = self._setupfunc() -
new file tests/regressiontests/context_processors/fixtures/context-processors-users.xml
diff -r 6490bd644de2 tests/regressiontests/context_processors/fixtures/context-processors-users.xml
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="100" model="auth.user"> 4 <field type="CharField" name="username">super</field> 5 <field type="CharField" name="first_name">Super</field> 6 <field type="CharField" name="last_name">User</field> 7 <field type="CharField" name="email">super@example.com</field> 8 <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field> 9 <field type="BooleanField" name="is_staff">True</field> 10 <field type="BooleanField" name="is_active">True</field> 11 <field type="BooleanField" name="is_superuser">True</field> 12 <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field> 13 <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field> 14 <field to="auth.group" name="groups" rel="ManyToManyRel"></field> 15 <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field> 16 </object> 17 </django-objects> -
new file tests/regressiontests/context_processors/templates/context_processors/auth_attrs_access.html
diff -r 6490bd644de2 tests/regressiontests/context_processors/templates/context_processors/auth_attrs_access.html
- + 1 {{ user.id }} -
new file tests/regressiontests/context_processors/templates/context_processors/auth_attrs_perms.html
diff -r 6490bd644de2 tests/regressiontests/context_processors/templates/context_processors/auth_attrs_perms.html
- + 1 {% if perms.auth %}Has auth permissions{% endif %} -
new file tests/regressiontests/context_processors/templates/context_processors/auth_attrs_test_access.html
diff -r 6490bd644de2 tests/regressiontests/context_processors/templates/context_processors/auth_attrs_test_access.html
- + 1 {% if session_accessed %}Session accessed{% else %}Session not accessed{% endif %} -
tests/regressiontests/context_processors/tests.py
diff -r 6490bd644de2 tests/regressiontests/context_processors/tests.py
a b 36 36 self.assertContains(response, url) 37 37 response = self.client.post(url, {'path': '/blah/'}) 38 38 self.assertContains(response, url) 39 40 class AuthContextProcessorTests(TestCase): 41 """ 42 Tests for the ``django.core.context_processors.auth`` processor 43 """ 44 urls = 'regressiontests.context_processors.urls' 45 fixtures = ['context-processors-users.xml'] 46 47 def test_session_not_accessed(self): 48 """ 49 Tests that the session is not accessed simply by including 50 the auth context processor 51 """ 52 response = self.client.get('/auth_processor_no_attr_access/') 53 self.assertContains(response, "Session not accessed") 54 55 def test_session_is_accessed(self): 56 """ 57 Tests that the session is accessed if the auth context processor 58 is used and relevant attributes accessed. 59 """ 60 response = self.client.get('/auth_processor_attr_access/') 61 self.assertContains(response, "Session accessed") 62 63 def test_perms_attrs(self): 64 self.client.login(username='super', password='secret') 65 response = self.client.get('/auth_processor_perms/') 66 self.assertContains(response, "Has auth permissions") -
tests/regressiontests/context_processors/urls.py
diff -r 6490bd644de2 tests/regressiontests/context_processors/urls.py
a b 5 5 6 6 urlpatterns = patterns('', 7 7 (r'^request_attrs/$', views.request_processor), 8 (r'^auth_processor_no_attr_access/$', views.auth_processor_no_attr_access), 9 (r'^auth_processor_attr_access/$', views.auth_processor_attr_access), 10 (r'^auth_processor_perms/$', views.auth_processor_perms), 8 11 ) -
tests/regressiontests/context_processors/views.py
diff -r 6490bd644de2 tests/regressiontests/context_processors/views.py
a b 6 6 def request_processor(request): 7 7 return render_to_response('context_processors/request_attrs.html', 8 8 RequestContext(request, {}, processors=[context_processors.request])) 9 10 def auth_processor_no_attr_access(request): 11 r1 = render_to_response('context_processors/auth_attrs_no_access.html', 12 RequestContext(request, {}, processors=[context_processors.auth])) 13 # *After* rendering, we check whether the session was accessed 14 return render_to_response('context_processors/auth_attrs_test_access.html', 15 {'session_accessed':request.session.accessed}) 16 17 def auth_processor_attr_access(request): 18 r1 = render_to_response('context_processors/auth_attrs_access.html', 19 RequestContext(request, {}, processors=[context_processors.auth])) 20 return render_to_response('context_processors/auth_attrs_test_access.html', 21 {'session_accessed':request.session.accessed}) 22 23 def auth_processor_perms(request): 24 return render_to_response('context_processors/auth_attrs_perms.html', 25 RequestContext(request, {}, processors=[context_processors.auth]))