allow to override field config_type and set custom additional fields

This commit is contained in:
Petr Dlouhý 2015-06-08 16:13:40 +02:00
parent f3604a3a73
commit 12245b0f71
4 changed files with 55 additions and 6 deletions

View file

@ -15,6 +15,7 @@ from django.template.context import RequestContext
from django.utils import six
from django.utils.formats import localize
from django.utils.translation import ugettext_lazy as _
import django
try:
from django.utils.encoding import smart_bytes
@ -51,6 +52,17 @@ FIELDS = {
float: (fields.FloatField, {'widget': NUMERIC_WIDGET}),
}
def parse_additional_fields(fields):
for key in fields:
field = fields[key]
field[0] = eval(field[0])
if 'widget' in field[1]:
field[1]['widget'] = eval(field[1]['widget'])
return fields
FIELDS.update(parse_additional_fields(settings.ADDITIONAL_FIELDS))
if not six.PY3:
FIELDS.update({
long: INTEGER_LIKE,
@ -65,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 "
@ -111,8 +128,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())))
@ -136,7 +153,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

View file

@ -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)

View file

@ -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)

View file

@ -53,6 +53,33 @@ admin will show.
See the :ref:`Backends <backends>` section how to setup the backend and
finish the configuration.
Custom fields
-------------
You can set the field type by the third value in the `CONSTANCE_CONFIG`
tuple. The value can be string or one of the supported types:
.. code-block:: python
'THE_ANSWER': (42, 'Answer to the Ultimate Question of Life, '
'The Universe, and Everything', str),
If you can add your custom field types, you can use the
`CONSTANCE_ADDITIONAL_FIELDS` variable. Note that you must
use later evaluated strings instead of direct classes:
.. code-block:: python
CONSTANCE_ADDITIONAL_FIELDS = {
'yes_no_null_select': ['django.forms.fields.ChoiceField',
{
'widget': 'django.forms.Select',
'choices': (("-----", None), ("yes", "Yes"), ("no", "No"))
}],
}
CONSTANCE_CONFIG = {
'MY_SELECT_KEY': ('yes', 'select yes or no', 'yes_no_null_select'),
}
Usage
-----