1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
"""
Preferences are regular Python objects that can be declared within any django app.
Once declared and registered, they can be edited by admins (for :py:class:`SitePreference` and :py:class:`GlobalPreference`)
and regular Users (for :py:class:`UserPreference`)
UserPreference, SitePreference and GlobalPreference are mapped to corresponding PreferenceModel,
which store the actual values.
"""
from __future__ import unicode_literals
import re
import warnings
from .settings import preferences_settings
from .exceptions import MissingDefault
from .serializers import UNSET
class InvalidNameError(ValueError):
pass
def check_name(name, obj):
error = None
if not re.match(r"^\w+$", name):
error = "Non-alphanumeric / underscore characters are forbidden in section and preferences names"
if preferences_settings.SECTION_KEY_SEPARATOR in name:
error = 'Sequence "{0}" is forbidden in section and preferences name, since it is used to access values via managers'.format(
preferences_settings.SECTION_KEY_SEPARATOR
)
if error:
full_message = 'Invalid name "{0}" while instanciating {1} object: {2}'.format(
name, obj, error
)
raise InvalidNameError(full_message)
class Section(object):
def __init__(self, name, verbose_name=None):
self.name = name
self.verbose_name = verbose_name or name
if preferences_settings.VALIDATE_NAMES and name:
check_name(self.name, self)
def __str__(self):
if not self.verbose_name:
return ""
return str(self.verbose_name)
EMPTY_SECTION = Section(None)
class AbstractPreference(object):
"""
A base class that handle common logic for preferences
"""
#: The section under which the preference will be registered
section = EMPTY_SECTION
#: The preference name
name = ""
#: A default value for the preference
default = UNSET
def __init__(self, registry=None):
if preferences_settings.VALIDATE_NAMES:
check_name(self.name, self)
if self.section and not hasattr(self.section, "name"):
self.section = Section(name=self.section)
warnings.warn(
"Implicit section instanciation is deprecated and "
"will be removed in future versions of django-dynamic-preferences",
DeprecationWarning,
stacklevel=2,
)
self.registry = registry
if self.default == UNSET and not getattr(self, "get_default", None):
raise MissingDefault
def get(self, attr, default=None):
getter = "get_{0}".format(attr)
if hasattr(self, getter):
return getattr(self, getter)()
return getattr(self, attr, default)
@property
def model(self):
return self.registry.preference_model
def identifier(self):
"""
Return the name and the section of the Preference joined with a separator, with the form `section<separator>name`
"""
if not self.section or not self.section.name:
return self.name
return preferences_settings.SECTION_KEY_SEPARATOR.join(
[self.section.name, self.name]
)
|