diff --git a/constance/admin.py b/constance/admin.py index 58ba909..37c3cd3 100644 --- a/constance/admin.py +++ b/constance/admin.py @@ -15,7 +15,9 @@ from django.template.response import TemplateResponse from django.utils import six from django.utils.encoding import smart_bytes from django.utils.formats import localize +from django.utils.module_loading import import_string from django.utils.translation import ugettext_lazy as _ +import django from . import LazyConfig, settings @@ -42,6 +44,25 @@ FIELDS = { float: (fields.FloatField, {'widget': NUMERIC_WIDGET}), } + +def parse_additional_fields(fields): + for key in fields: + field = fields[key] + + field[0] = import_string(field[0]) + + if 'widget' in field[1]: + klass = import_string(field[1]['widget']) + field[1]['widget'] = klass(**(field[1].get('widget_kwargs', {}) or {})) + + if 'widget_kwargs' in field[1]: + del field[1]['widget_kwargs'] + + return fields + + +FIELDS.update(parse_additional_fields(settings.ADDITIONAL_FIELDS)) + if not six.PY3: FIELDS.update({ long: INTEGER_LIKE, @@ -56,8 +77,13 @@ class ConstanceForm(forms.Form): super(ConstanceForm, self).__init__(*args, initial=initial, **kwargs) version_hash = hashlib.md5() - for name, (default, help_text) in settings.CONFIG.items(): - config_type = type(default) + for name, options in settings.CONFIG.items(): + default, help_text = options[0], options[1] + if len(options) == 3: + config_type = options[2] + else: + config_type = type(default) + if config_type not in FIELDS: raise ImproperlyConfigured(_("Constance doesn't support " "config values of the type " @@ -103,8 +129,8 @@ class ConstanceAdmin(admin.ModelAdmin): # First load a mapping between config name and default value if not self.has_change_permission(request, None): raise PermissionDenied - default_initial = ((name, default) - for name, (default, help_text) in settings.CONFIG.items()) + default_initial = ((name, options[0]) + for name, options in settings.CONFIG.items()) # Then update the mapping with actually values from the backend initial = dict(default_initial, **dict(config._backend.mget(settings.CONFIG.keys()))) @@ -128,7 +154,8 @@ class ConstanceAdmin(admin.ModelAdmin): 'form': form, 'media': self.media + form.media, } - for name, (default, help_text) in settings.CONFIG.items(): + for name, options in settings.CONFIG.items(): + default, help_text = options[0], options[1] # First try to load the value from the actual backend value = initial.get(name) # Then if the returned value is None, get the default diff --git a/constance/base.py b/constance/base.py index 99afe62..72812ad 100644 --- a/constance/base.py +++ b/constance/base.py @@ -11,7 +11,9 @@ class Config(object): def __getattr__(self, key): try: - default, help_text = settings.CONFIG[key] + if not len(settings.CONFIG[key]) in (2, 3): + raise AttributeError(key) + default = settings.CONFIG[key][0] except KeyError: raise AttributeError(key) result = self._backend.get(key) diff --git a/constance/settings.py b/constance/settings.py index 6f1350d..fd5edd4 100644 --- a/constance/settings.py +++ b/constance/settings.py @@ -5,6 +5,8 @@ BACKEND = getattr(settings, 'CONSTANCE_BACKEND', CONFIG = getattr(settings, 'CONSTANCE_CONFIG', {}) +ADDITIONAL_FIELDS = getattr(settings, 'CONSTANCE_ADDITIONAL_FIELDS', {}) + DATABASE_CACHE_BACKEND = getattr(settings, 'CONSTANCE_DATABASE_CACHE_BACKEND', None) diff --git a/constance/templates/admin/constance/change_list.html b/constance/templates/admin/constance/change_list.html index 746e263..71c7da1 100644 --- a/constance/templates/admin/constance/change_list.html +++ b/constance/templates/admin/constance/change_list.html @@ -36,7 +36,7 @@ {% block bodyclass %}change-list{% endblock %} {% block content %} -