From: Matías Aguirre Date: Mon, 9 Jul 2012 06:19:04 +0000 (-0300) Subject: Lazy dict wrapper to void hitting the DB when not needed. Closes #387 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=78670c422962c29479636ca1099faeda4501cc1e;p=django-social-auth.git Lazy dict wrapper to void hitting the DB when not needed. Closes #387 --- diff --git a/social_auth/context_processors.py b/social_auth/context_processors.py index 1668887..67c1fac 100644 --- a/social_auth/context_processors.py +++ b/social_auth/context_processors.py @@ -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): diff --git a/social_auth/utils.py b/social_auth/utils.py index 7c9a1f6..499f3f7 100644 --- a/social_auth/utils.py +++ b/social_auth/utils.py @@ -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()