]> git.parisson.com Git - django-social-auth.git/commitdiff
Lazy dict wrapper to void hitting the DB when not needed. Closes #387
authorMatías Aguirre <matiasaguirre@gmail.com>
Mon, 9 Jul 2012 06:19:04 +0000 (03:19 -0300)
committerMatías Aguirre <matiasaguirre@gmail.com>
Mon, 9 Jul 2012 06:19:04 +0000 (03:19 -0300)
social_auth/context_processors.py
social_auth/utils.py

index 16688872125e2387abcede2244777ec2db6264f5..67c1fac23d3e81096929a4affaab18c80d646c6d 100644 (file)
@@ -2,7 +2,7 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
 
 from social_auth.models import UserSocialAuth
 from social_auth.backends import get_backends
-from social_auth.utils import group_backend_by_type
+from social_auth.utils import group_backend_by_type, LazyDict
 
 # Note: social_auth_backends, social_auth_by_type_backends and
 #       social_auth_by_name_backends don't play nice together.
@@ -12,7 +12,9 @@ def social_auth_backends(request):
     """Load Social Auth current user data to context.
     Will add a output from backends_data to context under social_auth key.
     """
-    return {'social_auth': backends_data(request.user)}
+    def context_value():
+        return backends_data(request.user)
+    return {'social_auth': LazyDict(context_value)}
 
 
 def social_auth_by_type_backends(request):
@@ -20,12 +22,16 @@ def social_auth_by_type_backends(request):
     Will add a output from backends_data to context under social_auth key where
     each entry will be grouped by backend type (openid, oauth, oauth2).
     """
-    data = backends_data(request.user)
-    data['backends'] = group_backend_by_type(data['backends'])
-    data['not_associated'] = group_backend_by_type(data['not_associated'])
-    data['associated'] = group_backend_by_type(data['associated'],
-                                              key=lambda assoc: assoc.provider)
-    return {'social_auth': data}
+    def context_value():
+        data = backends_data(request.user)
+        data['backends'] = group_backend_by_type(data['backends'])
+        data['not_associated'] = group_backend_by_type(data['not_associated'])
+        data['associated'] = group_backend_by_type(
+            data['associated'],
+            key=lambda assoc: assoc.provider
+        )
+        return data
+    return {'social_auth': LazyDict(context_value)}
 
 
 def social_auth_by_name_backends(request):
@@ -36,15 +42,15 @@ def social_auth_by_name_backends(request):
     with a hyphen have the hyphen replaced with an underscore, e.g.
     google-oauth2 becomes google_oauth2 when referenced in templates.
     """
-    keys = get_backends().keys()
-    accounts = dict(zip(keys, [None] * len(keys)))
-    user = request.user
-
-    if hasattr(user, 'is_authenticated') and user.is_authenticated():
-        accounts.update((assoc.provider.replace('-', '_'), assoc)
+    def context_value():
+        keys = get_backends().keys()
+        accounts = dict(zip(keys, [None] * len(keys)))
+        user = request.user
+        if hasattr(user, 'is_authenticated') and user.is_authenticated():
+            accounts.update((assoc.provider.replace('-', '_'), assoc)
                     for assoc in UserSocialAuth.get_social_auth_for_user(user))
-
-    return {'social_auth': accounts}
+        return accounts
+    return {'social_auth': LazyDict(context_value)}
 
 
 def backends_data(user):
index 7c9a1f6220cf23f4836fb08d1eed37debc326a45..499f3f7d27b91171ed49c22e03850904804ecebf 100644 (file)
@@ -11,6 +11,7 @@ from datetime import timedelta, tzinfo
 from django.conf import settings
 from django.db.models import Model
 from django.contrib.contenttypes.models import ContentType
+from django.utils.functional import SimpleLazyObject
 
 
 try:
@@ -226,6 +227,19 @@ def url_add_parameters(url, params):
     return url
 
 
+class LazyDict(SimpleLazyObject):
+    """Lazy dict initialization."""
+    def __getitem__(self, name):
+        if self._wrapped is None:
+            self._setup()
+        return self._wrapped[name]
+
+    def __setitem__(self, name, value):
+        if self._wrapped is None:
+            self._setup()
+        self._wrapped[name] = value
+
+
 if __name__ == '__main__':
     import doctest
     doctest.testmod()