diff --git a/basetheme_bootstrap/admin.py b/basetheme_bootstrap/admin.py index 56f646eff710821f6fa9dc4e4f48d200facaca33..b5863cf5074c96377f4dd8d50cf768fea03eab5e 100644 --- a/basetheme_bootstrap/admin.py +++ b/basetheme_bootstrap/admin.py @@ -5,7 +5,7 @@ from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import ugettext -from basetheme_bootstrap.user_preferences import get_user_preference_class +from basetheme_bootstrap.user_preferences_utils import get_user_preference_class class ViewOnSiteModelAdmin(admin.ModelAdmin): diff --git a/basetheme_bootstrap/context_processors.py b/basetheme_bootstrap/context_processors.py index 6a69ce198f9af138ab56be93590ade7292006628..8c66e1fdf376c0d5f55e5d4568115787de63b431 100644 --- a/basetheme_bootstrap/context_processors.py +++ b/basetheme_bootstrap/context_processors.py @@ -4,7 +4,7 @@ from django.conf import settings from django.core.cache import cache from basetheme_bootstrap.templatetags.basetheme_bootstrap import basetheme_bootstrap_template_if_not_redefined -from basetheme_bootstrap.user_preferences import get_user_preferences_for_user +from basetheme_bootstrap.user_preferences_utils import get_user_preferences_for_user logger = logging.getLogger("basetheme_bootstrap") diff --git a/basetheme_bootstrap/tests.py b/basetheme_bootstrap/tests.py index c2f9beaef7c16c707cde0b0f00299abe127a275d..e32dcb07c5c2d76da4483013a815d80226d9052e 100644 --- a/basetheme_bootstrap/tests.py +++ b/basetheme_bootstrap/tests.py @@ -10,8 +10,8 @@ from django.core.exceptions import ValidationError from django.test import TestCase, RequestFactory, override_settings from django.urls import reverse -from basetheme_bootstrap import user_preferences, tokens -from basetheme_bootstrap.user_preferences import get_user_preferences_for_user +from basetheme_bootstrap import user_preferences_utils, tokens +from basetheme_bootstrap.user_preferences_utils import get_user_preferences_for_user class AboutPageTests(TestCase): @@ -510,19 +510,19 @@ class UserPreferencesTests(TestCase): def test_when_enabled_that_it_works(self): if not getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED", False): return - self.assertIsNotNone(user_preferences.get_user_preference_class()) - pref = user_preferences.get_user_preferences_for_user(self.user) + self.assertIsNotNone(user_preferences_utils.get_user_preference_class()) + pref = user_preferences_utils.get_user_preferences_for_user(self.user) self.assertIsNotNone(pref) - default_pref = user_preferences.get_user_preferences_for_user(None) + default_pref = user_preferences_utils.get_user_preferences_for_user(None) self.assertIsNotNone(default_pref) self.assertNotEqual(pref, default_pref) def test_when_enabled_that_it_works_2(self): if not getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED", False): return - default_pref = user_preferences.get_user_preferences_for_user(None) + default_pref = user_preferences_utils.get_user_preferences_for_user(None) self.assertIsNotNone(default_pref) - pref = user_preferences.get_user_preferences_for_user(self.user) + pref = user_preferences_utils.get_user_preferences_for_user(self.user) self.assertIsNotNone(pref) self.assertNotEqual(pref, default_pref) @@ -533,16 +533,16 @@ class UserPreferencesTests(TestCase): pref.save() str(pref) - default_pref = user_preferences.get_user_preferences_for_user(None) + default_pref = user_preferences_utils.get_user_preferences_for_user(None) self.assertIsNotNone(default_pref) - pref = user_preferences.get_user_preferences_for_user(self.user) + pref = user_preferences_utils.get_user_preferences_for_user(self.user) self.assertIsNotNone(pref) self.assertNotEqual(pref, default_pref) def test_only_one_default_pref(self): if not getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED", False): return - pref = user_preferences.get_user_preferences_for_user(self.user) + pref = user_preferences_utils.get_user_preferences_for_user(self.user) pref.user = None self.assertRaises(ValidationError, pref.save) @@ -550,7 +550,7 @@ class UserPreferencesTests(TestCase): get_user_preferences_for_user(AnonymousUser()) def test_caching_disabled_status_when_it_is_the_case(self): - user_preferences.get_user_preference_class() + user_preferences_utils.get_user_preference_class() self.assertTrue( cache.get("has_no_user_preferences_model", False) or getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED", False) @@ -572,9 +572,9 @@ class SignUpTestsUserPrefDown(SignUpTests): 'password2': "user@mp.comuser@mp.comuser@mp.comuser@mp.com", 'first_name': "user" }) - user_preferences.get_user_preference_class() - user_preferences.get_user_preference_class() - user_preferences.get_user_preferences_for_user(get_user_model().objects.first()) + user_preferences_utils.get_user_preference_class() + user_preferences_utils.get_user_preference_class() + user_preferences_utils.get_user_preferences_for_user(get_user_model().objects.first()) def setUp(self): cache.clear() diff --git a/basetheme_bootstrap/user_preferences.py b/basetheme_bootstrap/user_preferences.py index 6acedcde127b213ff137be11cdb0b261afc8bc58..9c92e69d1a02b431827fb61580426f2c2d659721 100644 --- a/basetheme_bootstrap/user_preferences.py +++ b/basetheme_bootstrap/user_preferences.py @@ -8,37 +8,11 @@ from django.core.exceptions import ValidationError from django.db import models from django.utils.translation import ugettext_lazy as _, ugettext -logger = logging.getLogger("basetheme_bootstrap") - - -def get_user_preference_class(): - if cache.get("has_no_user_preferences_model", False): - return None - if not getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED", False): - cache.set("has_no_user_preferences_model", True, None) - return None - try: - return apps.get_model( - app_label=getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_LOCATION_APP", "your_app"), - model_name=getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_NAME", "UserPreferences"), - ) - except LookupError as e: - logging.error("Either create the UserPreferences model, " - "or set BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED to False") - cache.set("has_no_user_preferences_model", True, None) - return None - - -def get_user_preferences_for_user(user): - if cache.get("has_no_user_preferences_model", False): - return None - klass = get_user_preference_class() - if klass is None: - return None - return klass.get_for_user(user=user) +from basetheme_bootstrap import user_preferences_utils +logger = logging.getLogger("basetheme_bootstrap") -class UserPreferencesAbstractModel(models.Model): +class UserPreferencesAbstractModel(user_preferences_utils.UserPreferencesAbstractModelWithUser): class Meta: abstract = True @@ -49,71 +23,4 @@ class UserPreferencesAbstractModel(models.Model): null=True, related_name="user_preferences", help_text=_("Leave blank for default user") - ) - - @classmethod - def get_for_user(cls, user): - try: - pref = cls.objects.get(user=user) - except cls.MultipleObjectsReturned: - for p in cls.objects.filter(user=None)[1:]: - p.delete() - pref = cls.objects.get(user=user) - except TypeError: - return cls.get_for_user(None) - except cls.DoesNotExist: - try: - pref, _ = cls.objects.get_or_create(user=None) - except cls.MultipleObjectsReturned: - for p in cls.objects.filter(user=None)[1:]: - p.delete() - pref, _ = cls.objects.get(user=None) - if user is not None: - pref.pk = None - pref.id = None - pref.user = user - pref.save() - return pref - - def full_clean(self, **kwargs): - # Checking for coherency on default preferences (user is None) - if self.user is None: - try: - default_pref = self.__class__.objects.get(user=None) - if default_pref.id != self.id: - raise ValidationError('Can\'t have more than one default preferences object, specify a user.') - except self.__class__.DoesNotExist: - pass - - return super().full_clean(**kwargs) - - def save(self, *args, **kwargs): - self.full_clean() - return super().save(*args, **kwargs) - - def __str__(self): - return ugettext("Default preferences") if self.user is None else '%s (%s)' % ( - self.user.username, - self._meta.verbose_name.title(), - ) - - @classmethod - def get_allowed_fields(cls): - if cls.preferences_groups is not None: - for group, fields in cls.preferences_groups.items(): - for f in fields: - yield f - return - for field_name in [f.name for f in cls._meta.get_fields()]: - if field_name == "id" or field_name == "pk" or field_name == "user": - continue - yield field_name - - @classmethod - @property - def preferences_groups(cls): - return None - - @property - def preferences_groups_descriptions(self): - return {} + ) \ No newline at end of file diff --git a/basetheme_bootstrap/user_preferences_utils.py b/basetheme_bootstrap/user_preferences_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..becbe80fa80fc3d5d51c082c2fa771f3198aca0b --- /dev/null +++ b/basetheme_bootstrap/user_preferences_utils.py @@ -0,0 +1,110 @@ +import logging + +from django.apps import apps +from django.conf import settings +from django.contrib.auth import get_user_model +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.db import models +from django.utils.translation import ugettext_lazy as _, ugettext + +logger = logging.getLogger("basetheme_bootstrap") + + +def get_user_preference_class(): + if cache.get("has_no_user_preferences_model", False): + return None + if not getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED", False): + cache.set("has_no_user_preferences_model", True, None) + return None + try: + return apps.get_model( + app_label=getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_LOCATION_APP", "your_app"), + model_name=getattr(settings, "BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_NAME", "UserPreferences"), + ) + except LookupError as e: + logging.error("Either create the UserPreferences model, " + "or set BASETHEME_BOOTSTRAP_USER_PREFERENCE_MODEL_ENABLED to False") + cache.set("has_no_user_preferences_model", True, None) + return None + + +def get_user_preferences_for_user(user): + if cache.get("has_no_user_preferences_model", False): + return None + klass = get_user_preference_class() + if klass is None: + return None + return klass.get_for_user(user=user) + + +class UserPreferencesAbstractModelWithUser(models.Model): + class Meta: + abstract = True + + @classmethod + def get_for_user(cls, user): + try: + pref = cls.objects.get(user=user) + except cls.MultipleObjectsReturned: + for p in cls.objects.filter(user=None)[1:]: + p.delete() + pref = cls.objects.get(user=user) + except TypeError: + return cls.get_for_user(None) + except cls.DoesNotExist: + try: + pref, _ = cls.objects.get_or_create(user=None) + except cls.MultipleObjectsReturned: + for p in cls.objects.filter(user=None)[1:]: + p.delete() + pref, _ = cls.objects.get(user=None) + if user is not None: + pref.pk = None + pref.id = None + pref.user = user + pref.save() + return pref + + def full_clean(self, **kwargs): + # Checking for coherency on default preferences (user is None) + if self.user is None: + try: + default_pref = self.__class__.objects.get(user=None) + if default_pref.id != self.id: + raise ValidationError('Can\'t have more than one default preferences object, specify a user.') + except self.__class__.DoesNotExist: + pass + + return super().full_clean(**kwargs) + + def save(self, *args, **kwargs): + self.full_clean() + return super().save(*args, **kwargs) + + def __str__(self): + return ugettext("Default preferences") if self.user is None else '%s (%s)' % ( + self.user.username, + self._meta.verbose_name.title(), + ) + + @classmethod + def get_allowed_fields(cls): + if cls.preferences_groups is not None: + for group, fields in cls.preferences_groups.items(): + for f in fields: + yield f + return + for field_name in [f.name for f in cls._meta.get_fields()]: + if field_name == "id" or field_name == "pk" or field_name == "user": + continue + yield field_name + + @classmethod + @property + def preferences_groups(cls): + return None + + @property + def preferences_groups_descriptions(self): + return {} diff --git a/basetheme_bootstrap/views.py b/basetheme_bootstrap/views.py index d4c6a74cec47ff391cc6555cf226e4ba50cb4d07..b645adb2dcde9499e5189fdee4aad5fa5f80ebfe 100644 --- a/basetheme_bootstrap/views.py +++ b/basetheme_bootstrap/views.py @@ -21,7 +21,7 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.translation import ugettext from basetheme_bootstrap import tokens -from basetheme_bootstrap import user_preferences +from basetheme_bootstrap import user_preferences_utils from basetheme_bootstrap.default_settings import is_validating_email from basetheme_bootstrap.forms import UserCreationFormWithMore, \ MyUserChangeForm, UserDeleteForm @@ -217,7 +217,7 @@ def user_delete(request): @login_required def account_detail(request): - klass = user_preferences.get_user_preference_class() + klass = user_preferences_utils.get_user_preference_class() if klass is None: form_prefs = None else: diff --git a/setup.py b/setup.py index dbd4bb6319f2dce544a92471b4784e5a42422d68..8be51ebe2ccdabc2c99de822ec281674ec06f3a2 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ readme = open('README.rst').read() setup( name='django-basetheme-bootstrap', - version='0.2.60', + version='0.2.61', description='Django Basetheme Bootstrap', long_description=readme, author='Bryan Brancotte',