diff --git a/.travis.yml b/.travis.yml index c2acafb9f7aeeb6ec8f1b7cc99aafd2c3ba44304..5a464da6fc5db52e91af4f92c8b6684abac1e5c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,12 @@ python: - 3.4 - 3.5 - 3.6 + - 3.7 env: - DJANGO='django>=1.10,<1.11' - DJANGO='django>=1.11,<2.0' - - DJANGO='django>=2.0,<2.1' + - DJANGO='django>=2.0' install: - travis_retry pip install $DJANGO diff --git a/constance/__init__.py b/constance/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ac30b720729b4a64970613383e5c4e054278231a --- /dev/null +++ b/constance/__init__.py @@ -0,0 +1,14 @@ +from django.utils.functional import LazyObject + +__version__ = '2.2.0' + +default_app_config = 'constance.apps.ConstanceConfig' + + +class LazyConfig(LazyObject): + def _setup(self): + from .base import Config + self._wrapped = Config() + + +config = LazyConfig() diff --git a/constance/admin.py b/constance/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..a2285cc04be7f71c276a3973abe8e65177b50a7f --- /dev/null +++ b/constance/admin.py @@ -0,0 +1,327 @@ +from collections import OrderedDict +from datetime import datetime, date, time, timedelta +from decimal import Decimal +from operator import itemgetter +import hashlib +import os + +from django import forms, VERSION +from django.apps import apps +from django.conf import settings as django_settings +from django.conf.urls import url +from django.contrib import admin, messages +from django.contrib.admin import widgets +from django.contrib.admin.options import csrf_protect_m +from django.core.exceptions import PermissionDenied, ImproperlyConfigured +from django.forms import fields +from django.http import HttpResponseRedirect +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 _ + +from . import LazyConfig, settings + + +config = LazyConfig() + + +NUMERIC_WIDGET = forms.TextInput(attrs={'size': 10}) + +INTEGER_LIKE = (fields.IntegerField, {'widget': NUMERIC_WIDGET}) +STRING_LIKE = (fields.CharField, { + 'widget': forms.Textarea(attrs={'rows': 3}), + 'required': False, +}) + +FIELDS = { + bool: (fields.BooleanField, {'required': False}), + int: INTEGER_LIKE, + Decimal: (fields.DecimalField, {'widget': NUMERIC_WIDGET}), + str: STRING_LIKE, + datetime: ( + fields.SplitDateTimeField, {'widget': widgets.AdminSplitDateTime} + ), + timedelta: ( + fields.DurationField, {'widget': widgets.AdminTextInputWidget} + ), + date: (fields.DateField, {'widget': widgets.AdminDateWidget}), + time: (fields.TimeField, {'widget': widgets.AdminTimeWidget}), + float: (fields.FloatField, {'widget': NUMERIC_WIDGET}), +} + + +def parse_additional_fields(fields): + for key in fields: + field = list(fields[key]) + + if len(field) == 1: + field.append({}) + + 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'] + + fields[key] = field + + return fields + + +FIELDS.update(parse_additional_fields(settings.ADDITIONAL_FIELDS)) + +if not six.PY3: + FIELDS.update({ + long: INTEGER_LIKE, + unicode: STRING_LIKE, + }) + + +def get_values(): + """ + Get dictionary of values from the backend + :return: + """ + + # First load a mapping between config name and default value + 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))) + + return initial + + +class ConstanceForm(forms.Form): + version = forms.CharField(widget=forms.HiddenInput) + + def __init__(self, initial, *args, **kwargs): + super(ConstanceForm, self).__init__(*args, initial=initial, **kwargs) + version_hash = hashlib.md5() + + for name, options in settings.CONFIG.items(): + default = options[0] + if len(options) == 3: + config_type = options[2] + if config_type not in settings.ADDITIONAL_FIELDS and not isinstance(default, config_type): + raise ImproperlyConfigured(_("Default value type must be " + "equal to declared config " + "parameter type. Please fix " + "the default value of " + "'%(name)s'.") + % {'name': name}) + else: + config_type = type(default) + + if config_type not in FIELDS: + raise ImproperlyConfigured(_("Constance doesn't support " + "config values of the type " + "%(config_type)s. Please fix " + "the value of '%(name)s'.") + % {'config_type': config_type, + 'name': name}) + field_class, kwargs = FIELDS[config_type] + self.fields[name] = field_class(label=name, **kwargs) + + version_hash.update(smart_bytes(initial.get(name, ''))) + self.initial['version'] = version_hash.hexdigest() + + def save(self): + for file_field in self.files: + file = self.cleaned_data[file_field] + file_path = os.path.join(django_settings.MEDIA_ROOT, file.name) + with open(file_path, 'wb+') as destination: + for chunk in file.chunks(): + destination.write(chunk) + self.cleaned_data[file_field] = file.name + + for name in settings.CONFIG: + if getattr(config, name) != self.cleaned_data[name]: + setattr(config, name, self.cleaned_data[name]) + + def clean_version(self): + value = self.cleaned_data['version'] + + if settings.IGNORE_ADMIN_VERSION_CHECK: + return value + + if value != self.initial['version']: + raise forms.ValidationError(_('The settings have been modified ' + 'by someone else. Please reload the ' + 'form and resubmit your changes.')) + return value + + def clean(self): + cleaned_data = super(ConstanceForm, self).clean() + + if not settings.CONFIG_FIELDSETS: + return cleaned_data + + field_name_list = [] + for fieldset_title, fields_list in settings.CONFIG_FIELDSETS.items(): + for field_name in fields_list: + field_name_list.append(field_name) + if field_name_list and set(set(settings.CONFIG.keys()) - set(field_name_list)): + raise forms.ValidationError(_('CONSTANCE_CONFIG_FIELDSETS is missing ' + 'field(s) that exists in CONSTANCE_CONFIG.')) + + return cleaned_data + + +class ConstanceAdmin(admin.ModelAdmin): + change_list_template = 'admin/constance/change_list.html' + change_list_form = ConstanceForm + + def get_urls(self): + info = self.model._meta.app_label, self.model._meta.module_name + return [ + url(r'^$', + self.admin_site.admin_view(self.changelist_view), + name='%s_%s_changelist' % info), + url(r'^$', + self.admin_site.admin_view(self.changelist_view), + name='%s_%s_add' % info), + ] + + def get_config_value(self, name, options, form, initial): + 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 + if value is None: + value = getattr(config, name) + config_value = { + 'name': name, + 'default': localize(default), + 'raw_default': default, + 'help_text': _(help_text), + 'value': localize(value), + 'modified': localize(value) != localize(default), + 'form_field': form[name], + 'is_date': isinstance(default, date), + 'is_datetime': isinstance(default, datetime), + 'is_checkbox': isinstance(form[name].field.widget, forms.CheckboxInput), + 'is_file': isinstance(form[name].field.widget, forms.FileInput), + } + + return config_value + + def get_changelist_form(self, request): + """ + Returns a Form class for use in the changelist_view. + """ + # Defaults to self.change_list_form in order to preserve backward + # compatibility + return self.change_list_form + + @csrf_protect_m + def changelist_view(self, request, extra_context=None): + if not self.has_change_permission(request, None): + raise PermissionDenied + initial = get_values() + form_cls = self.get_changelist_form(request) + form = form_cls(initial=initial) + if request.method == 'POST': + form = form_cls( + data=request.POST, files=request.FILES, initial=initial + ) + if form.is_valid(): + form.save() + messages.add_message( + request, + messages.SUCCESS, + _('Live settings updated successfully.'), + ) + return HttpResponseRedirect('.') + context = dict( + self.admin_site.each_context(request), + config_values=[], + title=self.model._meta.app_config.verbose_name, + app_label='constance', + opts=self.model._meta, + form=form, + media=self.media + form.media, + icon_type='gif' if VERSION < (1, 9) else 'svg', + ) + for name, options in settings.CONFIG.items(): + context['config_values'].append( + self.get_config_value(name, options, form, initial) + ) + + if settings.CONFIG_FIELDSETS: + context['fieldsets'] = [] + for fieldset_title, fields_list in settings.CONFIG_FIELDSETS.items(): + fields_exist = all(field in settings.CONFIG for field in fields_list) + assert fields_exist, "CONSTANCE_CONFIG_FIELDSETS contains field(s) that does not exist" + config_values = [] + + for name in fields_list: + options = settings.CONFIG.get(name) + if options: + config_values.append( + self.get_config_value(name, options, form, initial) + ) + + context['fieldsets'].append({ + 'title': fieldset_title, + 'config_values': config_values + }) + if not isinstance(settings.CONFIG_FIELDSETS, OrderedDict): + context['fieldsets'].sort(key=itemgetter('title')) + + if not isinstance(settings.CONFIG, OrderedDict): + context['config_values'].sort(key=itemgetter('name')) + request.current_app = self.admin_site.name + return TemplateResponse(request, self.change_list_template, context) + + def has_add_permission(self, *args, **kwargs): + return False + + def has_delete_permission(self, *args, **kwargs): + return False + + def has_change_permission(self, request, obj=None): + if settings.SUPERUSER_ONLY: + return request.user.is_superuser + return super(ConstanceAdmin, self).has_change_permission(request, obj) + + +class Config(object): + class Meta(object): + app_label = 'constance' + object_name = 'Config' + model_name = module_name = 'config' + verbose_name_plural = _('config') + abstract = False + swapped = False + + def get_ordered_objects(self): + return False + + def get_change_permission(self): + return 'change_%s' % self.model_name + + @property + def app_config(self): + return apps.get_app_config(self.app_label) + + @property + def label(self): + return '%s.%s' % (self.app_label, self.object_name) + + @property + def label_lower(self): + return '%s.%s' % (self.app_label, self.model_name) + + _meta = Meta() + + +admin.site.register([Config], ConstanceAdmin) diff --git a/constance/apps.py b/constance/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..25099a8c48342439a3aea916269cf4b4a4311816 --- /dev/null +++ b/constance/apps.py @@ -0,0 +1,35 @@ +from django.db.models import signals +from django.apps import AppConfig + + +class ConstanceConfig(AppConfig): + name = 'constance' + verbose_name = 'Constance' + + def ready(self): + super(ConstanceConfig, self).ready() + signals.post_migrate.connect(self.create_perm, + dispatch_uid='constance.create_perm') + + def create_perm(self, using=None, *args, **kwargs): + """ + Creates a fake content type and permission + to be able to check for permissions + """ + from django.conf import settings + from django.contrib.auth.models import Permission + from django.contrib.contenttypes.models import ContentType + + constance_dbs = getattr(settings, 'CONSTANCE_DBS', None) + if constance_dbs is not None and using not in constance_dbs: + return + if ContentType._meta.installed and Permission._meta.installed: + content_type, created = ContentType.objects.using(using).get_or_create( + app_label='constance', + model='config', + ) + + permission, created = Permission.objects.using(using).get_or_create( + content_type=content_type, + codename='change_config', + defaults={'name': 'Can change config'}) diff --git a/constance/backends/__init__.py b/constance/backends/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a64905eb9035fa64f74f41aa99e6e4d3d7005259 --- /dev/null +++ b/constance/backends/__init__.py @@ -0,0 +1,26 @@ +""" +Defines the base constance backend +""" + + +class Backend(object): + + def get(self, key): + """ + Get the key from the backend store and return the value. + Return None if not found. + """ + raise NotImplementedError + + def mget(self, keys): + """ + Get the keys from the backend store and return a list of the values. + Return an empty list if not found. + """ + raise NotImplementedError + + def set(self, key, value): + """ + Add the value to the backend store given the key. + """ + raise NotImplementedError diff --git a/constance/backends/database/__init__.py b/constance/backends/database/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..454b5001717f11a862c08d00a85baf8f99041fb1 --- /dev/null +++ b/constance/backends/database/__init__.py @@ -0,0 +1,109 @@ +from django.core.cache import caches +from django.core.cache.backends.locmem import LocMemCache +from django.core.exceptions import ImproperlyConfigured +from django.db import OperationalError, ProgrammingError +from django.db.models.signals import post_save + +from .. import Backend +from ... import settings, signals, config + + +class DatabaseBackend(Backend): + def __init__(self): + from .models import Constance + self._model = Constance + self._prefix = settings.DATABASE_PREFIX + self._autofill_timeout = settings.DATABASE_CACHE_AUTOFILL_TIMEOUT + self._autofill_cachekey = 'autofilled' + + if not self._model._meta.installed: + raise ImproperlyConfigured( + "The constance.backends.database app isn't installed " + "correctly. Make sure it's in your INSTALLED_APPS setting.") + + if settings.DATABASE_CACHE_BACKEND: + self._cache = caches[settings.DATABASE_CACHE_BACKEND] + if isinstance(self._cache, LocMemCache): + raise ImproperlyConfigured( + "The CONSTANCE_DATABASE_CACHE_BACKEND setting refers to a " + "subclass of Django's local-memory backend (%r). Please " + "set it to a backend that supports cross-process caching." + % settings.DATABASE_CACHE_BACKEND) + else: + self._cache = None + self.autofill() + # Clear simple cache. + post_save.connect(self.clear, sender=self._model) + + def add_prefix(self, key): + return "%s%s" % (self._prefix, key) + + def autofill(self): + if not self._autofill_timeout or not self._cache: + return + full_cachekey = self.add_prefix(self._autofill_cachekey) + if self._cache.get(full_cachekey): + return + autofill_values = {} + autofill_values[full_cachekey] = 1 + for key, value in self.mget(settings.CONFIG): + autofill_values[self.add_prefix(key)] = value + self._cache.set_many(autofill_values, timeout=self._autofill_timeout) + + def mget(self, keys): + if not keys: + return + keys = {self.add_prefix(key): key for key in keys} + try: + stored = self._model._default_manager.filter(key__in=keys) + for const in stored: + yield keys[const.key], const.value + except (OperationalError, ProgrammingError): + pass + + def get(self, key): + key = self.add_prefix(key) + if self._cache: + value = self._cache.get(key) + if value is None: + self.autofill() + value = self._cache.get(key) + else: + value = None + if value is None: + try: + value = self._model._default_manager.get(key=key).value + except (OperationalError, ProgrammingError, self._model.DoesNotExist): + pass + else: + if self._cache: + self._cache.add(key, value) + return value + + def set(self, key, value): + old_value = self.get(key) + + try: + constance, created = self._model._default_manager.get_or_create( + key=self.add_prefix(key), defaults={'value': value} + ) + except (OperationalError, ProgrammingError): + # database is not created, noop + return + + if not created: + constance.value = value + constance.save() + if self._cache: + self._cache.set(key, value) + + signals.config_updated.send( + sender=config, key=key, old_value=old_value, new_value=value + ) + + def clear(self, sender, instance, created, **kwargs): + if self._cache and not created: + keys = [self.add_prefix(k) for k in settings.CONFIG] + keys.append(self.add_prefix(self._autofill_cachekey)) + self._cache.delete_many(keys) + self.autofill() diff --git a/constance/backends/database/migrations/0001_initial.py b/constance/backends/database/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..e0ebd996c80fed5fdeb63719bcde7ed95e54196d --- /dev/null +++ b/constance/backends/database/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import picklefield.fields + + +class Migration(migrations.Migration): + dependencies = [] + + operations = [ + migrations.CreateModel( + name='Constance', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, + auto_created=True, serialize=False)), + ('key', models.CharField(unique=True, max_length=255)), + ('value', picklefield.fields.PickledObjectField(editable=False)), + ], + options={ + 'verbose_name': 'constance', + 'verbose_name_plural': 'constances', + 'db_table': 'constance_config', + }, + bases=(models.Model,), + ), + ] diff --git a/constance/backends/database/migrations/__init__.py b/constance/backends/database/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/constance/backends/database/models.py b/constance/backends/database/models.py new file mode 100644 index 0000000000000000000000000000000000000000..e9964e837085f888464d8eeabb1ac389abe9e1ce --- /dev/null +++ b/constance/backends/database/models.py @@ -0,0 +1,24 @@ +from django.db import models +from django.core.exceptions import ImproperlyConfigured + +from django.utils.translation import ugettext_lazy as _ + +try: + from picklefield import PickledObjectField +except ImportError: + raise ImproperlyConfigured("Couldn't find the the 3rd party app " + "django-picklefield which is required for " + "the constance database backend.") + + +class Constance(models.Model): + key = models.CharField(max_length=255, unique=True) + value = PickledObjectField() + + class Meta: + verbose_name = _('constance') + verbose_name_plural = _('constances') + db_table = 'constance_config' + + def __unicode__(self): + return self.key diff --git a/constance/backends/database/south_migrations/0001_initial.py b/constance/backends/database/south_migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..f9b747327eab828eddd2bcd12aab6453ec1afbdc --- /dev/null +++ b/constance/backends/database/south_migrations/0001_initial.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from south.db import db +from south.v2 import SchemaMigration + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Constance' + db.create_table('constance_config', ( + ('id', self.gf('django.db.models.fields.AutoField')( + primary_key=True)), + ('key', self.gf('django.db.models.fields.TextField')()), + ('value', self.gf('picklefield.fields.PickledObjectField')()), + )) + db.send_create_signal('database', ['Constance']) + + def backwards(self, orm): + # Deleting model 'Constance' + db.delete_table('constance_config') + + models = { + 'database.constance': { + 'Meta': {'object_name': 'Constance', + 'db_table': "'constance_config'"}, + 'id': ('django.db.models.fields.AutoField', [], + {'primary_key': 'True'}), + 'key': ('django.db.models.fields.TextField', [], {}), + 'value': ('picklefield.fields.PickledObjectField', [], {}) + } + } + + complete_apps = ['database'] diff --git a/constance/backends/database/south_migrations/0002_auto__chg_field_constance_key__add_unique_constance_key.py b/constance/backends/database/south_migrations/0002_auto__chg_field_constance_key__add_unique_constance_key.py new file mode 100644 index 0000000000000000000000000000000000000000..ef8fb3ce727b4585ec072fb403952e19df60a991 --- /dev/null +++ b/constance/backends/database/south_migrations/0002_auto__chg_field_constance_key__add_unique_constance_key.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from south.db import db +from south.v2 import SchemaMigration + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Changing field 'Constance.key' + db.alter_column('constance_config', 'key', + self.gf('django.db.models.fields.CharField')( + max_length=255)) + # Adding unique constraint on 'Constance', fields ['key'] + db.create_unique('constance_config', ['key']) + + def backwards(self, orm): + # Removing unique constraint on 'Constance', fields ['key'] + db.delete_unique('constance_config', ['key']) + + # Changing field 'Constance.key' + db.alter_column('constance_config', 'key', + self.gf('django.db.models.fields.TextField')()) + + models = { + 'database.constance': { + 'Meta': {'object_name': 'Constance', + 'db_table': "'constance_config'"}, + 'id': ('django.db.models.fields.AutoField', [], + {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], + {'unique': 'True', 'max_length': '255'}), + 'value': ('picklefield.fields.PickledObjectField', [], {}) + } + } + + complete_apps = ['database'] diff --git a/constance/backends/database/south_migrations/__init__.py b/constance/backends/database/south_migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/constance/backends/redisd.py b/constance/backends/redisd.py new file mode 100644 index 0000000000000000000000000000000000000000..c7d522e42fc3ba273e4085579604da50014e554f --- /dev/null +++ b/constance/backends/redisd.py @@ -0,0 +1,55 @@ +from django.core.exceptions import ImproperlyConfigured +from django.utils import six +from django.utils.six.moves import zip + +from . import Backend +from .. import settings, utils, signals, config + +try: + from cPickle import loads, dumps +except ImportError: + from pickle import loads, dumps + + +class RedisBackend(Backend): + + def __init__(self): + super(RedisBackend, self).__init__() + self._prefix = settings.REDIS_PREFIX + connection_cls = settings.REDIS_CONNECTION_CLASS + if connection_cls is not None: + self._rd = utils.import_module_attr(connection_cls)() + else: + try: + import redis + except ImportError: + raise ImproperlyConfigured( + "The Redis backend requires redis-py to be installed.") + if isinstance(settings.REDIS_CONNECTION, six.string_types): + self._rd = redis.from_url(settings.REDIS_CONNECTION) + else: + self._rd = redis.Redis(**settings.REDIS_CONNECTION) + + def add_prefix(self, key): + return "%s%s" % (self._prefix, key) + + def get(self, key): + value = self._rd.get(self.add_prefix(key)) + if value: + return loads(value) + return None + + def mget(self, keys): + if not keys: + return + prefixed_keys = [self.add_prefix(key) for key in keys] + for key, value in zip(keys, self._rd.mget(prefixed_keys)): + if value: + yield key, loads(value) + + def set(self, key, value): + old_value = self.get(key) + self._rd.set(self.add_prefix(key), dumps(value)) + signals.config_updated.send( + sender=config, key=key, old_value=old_value, new_value=value + ) diff --git a/constance/base.py b/constance/base.py new file mode 100644 index 0000000000000000000000000000000000000000..e44ff75a82b5e221c747e190b0edb48b5c8bd404 --- /dev/null +++ b/constance/base.py @@ -0,0 +1,32 @@ +from . import settings, utils + + +class Config(object): + """ + The global config wrapper that handles the backend. + """ + def __init__(self): + super(Config, self).__setattr__('_backend', + utils.import_module_attr(settings.BACKEND)()) + + def __getattr__(self, key): + try: + 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) + if result is None: + result = default + setattr(self, key, default) + return result + return result + + def __setattr__(self, key, value): + if key not in settings.CONFIG: + raise AttributeError(key) + self._backend.set(key, value) + + def __dir__(self): + return settings.CONFIG.keys() diff --git a/constance/context_processors.py b/constance/context_processors.py new file mode 100644 index 0000000000000000000000000000000000000000..3a3da33d7b7ac191f2066a122648c9e30e5ff395 --- /dev/null +++ b/constance/context_processors.py @@ -0,0 +1,15 @@ +import constance + + +def config(request): + """ + Simple context processor that puts the config into every + RequestContext. Just make sure you have a setting like this: + + TEMPLATE_CONTEXT_PROCESSORS = ( + # ... + 'constance.context_processors.config', + ) + + """ + return {"config": constance.config} diff --git a/constance/locale/cs_CZ/LC_MESSAGES/django.mo b/constance/locale/cs_CZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..4c9010077e4c79177133f60f34ddbb80297eb5bb Binary files /dev/null and b/constance/locale/cs_CZ/LC_MESSAGES/django.mo differ diff --git a/constance/locale/cs_CZ/LC_MESSAGES/django.po b/constance/locale/cs_CZ/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..ccfdf80b0e8b7ffa235143d31587404a45795eba --- /dev/null +++ b/constance/locale/cs_CZ/LC_MESSAGES/django.po @@ -0,0 +1,96 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django-constance\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: 2014-11-27 18:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/" +"django-constance/language/cs_CZ/)\n" +"Language: cs_CZ\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: admin.py:113 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Nastavení bylo úspěšně uloženo." + +#: admin.py:285 +msgid "config" +msgstr "nastavení" + +#: apps.py:8 +msgid "Constance" +msgstr "" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "konstanta" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "konstanty" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Uložit" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "Domů" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Název" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Výchozí hodnota" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Hodnota" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Je změněna?" + +#~ msgid "Constance config" +#~ msgstr "Nastavení konstant" diff --git a/constance/locale/de/LC_MESSAGES/django.mo b/constance/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..a0d65980fd11bcbf397dc61f6225c159ad5c8c52 Binary files /dev/null and b/constance/locale/de/LC_MESSAGES/django.mo differ diff --git a/constance/locale/de/LC_MESSAGES/django.po b/constance/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..705ab1ee780c5bb1616399f985cc542a11f31a5f --- /dev/null +++ b/constance/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,106 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Jannis Leidel , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django-constance\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: 2014-11-27 18:17+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: German (http://www.transifex.com/projects/p/django-constance/" +"language/de/)\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: admin.py:113 +#, fuzzy, python-format +#| msgid "" +#| "Constance doesn't support config values of the type %(config_type)s. " +#| "Please fix the value of '%(name)s'." +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" +"Konstanze unterstützt die Konfigurationswerte vom Typ %(config_type)s nicht. " +"Bitte den Ausgangswert von '%(name)s' ändern." + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" +"Konstanze unterstützt die Konfigurationswerte vom Typ %(config_type)s nicht. " +"Bitte den Ausgangswert von '%(name)s' ändern." + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" +"Die Konfiguration wurde seit Öffnen dieser Seite verändert. Bitte die Seite " +"neuladen und die Änderungen erneut vornehmen." + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Die Livekonfiguration wurde erfolgreich aktualisiert." + +#: admin.py:285 +msgid "config" +msgstr "Konfiguration" + +#: apps.py:8 +msgid "Constance" +msgstr "Konstanze" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "Konstanze" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "Konstanzes" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Sichern" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "Start" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Name" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Voreinstellung" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Wert" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Ist modifiziert" + +#~ msgid "Constance config" +#~ msgstr "Constance Konfiguration" diff --git a/constance/locale/en/LC_MESSAGES/django.mo b/constance/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..8319b4801f99dc60951c0488fa290c61e3d47cfe Binary files /dev/null and b/constance/locale/en/LC_MESSAGES/django.mo differ diff --git a/constance/locale/en/LC_MESSAGES/django.po b/constance/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..fa8d488aa50f50396ced482cfba4f76c1802efb0 --- /dev/null +++ b/constance/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.py:113 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "" + +#: admin.py:285 +msgid "config" +msgstr "" + +#: apps.py:8 +msgid "Constance" +msgstr "" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "" diff --git a/constance/locale/es/LC_MESSAGES/django.mo b/constance/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..55a6b6c0d3f0518ed8970c636f6fecf3139d9928 Binary files /dev/null and b/constance/locale/es/LC_MESSAGES/django.mo differ diff --git a/constance/locale/es/LC_MESSAGES/django.po b/constance/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..43b2b886180b32733f8f85c7da12628b882c2fc0 --- /dev/null +++ b/constance/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,106 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Igor Támara , 2015 +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Igor Támara \n" +"Language-Team: Spanish (http://www.transifex.com/projects/p/django-constance/" +"language/de/\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: admin.py:113 +#, fuzzy, python-format +#| msgid "" +#| "Constance doesn't support config values of the type %(config_type)s. " +#| "Please fix the value of '%(name)s'." +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" +"Constance no soporta valores de configuración de los tipos %(config_type)s. " +"Por favor arregle el valor de '%(name)s'." + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" +"Constance no soporta valores de configuración de los tipos %(config_type)s. " +"Por favor arregle el valor de '%(name)s'." + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" +"La configuración ha sido modificada por alguien más. Por favor recargue el " +"formulario y reenvíe sus cambios." + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Las configuraciones en vivo se actualizaron exitosamente." + +#: admin.py:285 +msgid "config" +msgstr "configuración" + +#: apps.py:8 +msgid "Constance" +msgstr "Constance" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "constance" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "constances" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Guardar" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "Inicio" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Nombre" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Predeterminado" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Valor" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Está modificado" + +#~ msgid "Constance config" +#~ msgstr "Configuración de Constance" diff --git a/constance/locale/et/LC_MESSAGES/django.mo b/constance/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..4208588504deba0ef553e24b8a5914a7cd608115 Binary files /dev/null and b/constance/locale/et/LC_MESSAGES/django.mo differ diff --git a/constance/locale/et/LC_MESSAGES/django.po b/constance/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..723bec9e5ef497746631cb4ad6715db20e40a69c --- /dev/null +++ b/constance/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,99 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: admin.py:113 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" +"Vaikimisi väärtus peab olema vastav seade parameetri tüübile. Palun " +"sisestagekorrekne vaikimisi väärtus väljale '%(name)s'" + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" +"Constance ei toeta seadete seda tüüpi %(config_type) seadete väärtusi. " +"Palunsisestage korrektne väärtus väljale '%(name)s'." + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" +"Seadeid on vahepeal muudetud, palun esitage oma muudatused peale seda kui " +"olete lehe uuesti laadinud" + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Seaded edukalt muudetud." + +#: admin.py:285 +msgid "config" +msgstr "konfiguratsioon" + +#: apps.py:8 +msgid "Constance" +msgstr "Seaded" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "seaded" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "seaded" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "Loe/salvesta andmebaasi põhiseid seadeid" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Salvesta" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Nimi" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Vaikimisi" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Väärtus" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Muudetud" diff --git a/constance/locale/fr/LC_MESSAGES/django.mo b/constance/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..116e58e52e5da05ae357b5b54270d19764dd3015 Binary files /dev/null and b/constance/locale/fr/LC_MESSAGES/django.mo differ diff --git a/constance/locale/fr/LC_MESSAGES/django.po b/constance/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..44cc39ca7767ae38fe15b67d3afa35fb1bf3aab1 --- /dev/null +++ b/constance/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-02 19:01+0100\n" +"PO-Revision-Date: 2017-07-03 12:35+0100\n" +"Last-Translator: Bruno Alla \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Language-Team: \n" +"X-Generator: Poedit 2.0.2\n" + +#: admin.py:111 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" +"Le type de la valeur par défaut doit être le même que le type déclaré dans " +"la configuration. Veuillez corriger la valeur par défaut de '%(name)s'." + +#: admin.py:121 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" +"Constance ne prend pas en charge les valeurs de configuration du type " +"%(config_type)s. Veuillez corriger la valeur de ‘%(name)s’." + +#: admin.py:145 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" +"Les paramètres ont été modifiés par quelqu'un d'autre. Veuillez rafraichir " +"le formulaire et soumettre de nouveau vos modifications." + +#: admin.py:209 +msgid "Live settings updated successfully." +msgstr "Paramètres mis à jour avec succès." + +#: admin.py:271 +msgid "config" +msgstr "config" + +#: apps.py:8 +msgid "Constance" +msgstr "Constance" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "constance" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "constances" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" +"Obtenir/définir les paramètres de configuration de base de données gérées " +"par Constance" + +#: templates/admin/constance/change_list.html:68 +msgid "Save" +msgstr "Enregistrer" + +#: templates/admin/constance/change_list.html:77 +msgid "Home" +msgstr "Index" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Nom" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Défaut" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Valeur" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Est modifié" diff --git a/constance/locale/it/LC_MESSAGES/django.mo b/constance/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..d621d3ba2f0c185c8d187fd528d1bb0a803d377a Binary files /dev/null and b/constance/locale/it/LC_MESSAGES/django.mo differ diff --git a/constance/locale/it/LC_MESSAGES/django.po b/constance/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..97e5d971ccbc32ba309be0c486e0104f595291a3 --- /dev/null +++ b/constance/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,105 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django-constance\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: 2018-03-13 15:26+0100\n" +"Last-Translator: Paolo Melchiorre \n" +"Language-Team: Italian (http://www.transifex.com/projects/p/django-constance/" +"language/it/)\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.4\n" + +#: admin.py:113 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" +"Il tipo dei valori di default deve essere uguale al tipo del parametro. " +"Modifica il valore di default di '%(name)s'." + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" +"Constance non supporta valori di impostazioni di tipo %(config_type)s. " +"Modifica il valore di '%(name)s'." + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" +"Le impostazioni sono state modificate da qualcuno. Ricarica la pagina e " +"invia nuovamente le tue modifiche." + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" +"CONSTANCE_CONFIG_FIELDSETS non contiene campi che esistono in " +"CONSTANCE_CONFIG." + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Le impostazioni attive sono state aggiornate correttamente." + +#: admin.py:285 +msgid "config" +msgstr "configurazioni" + +#: apps.py:8 +msgid "Constance" +msgstr "Impostazioni" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "impostazione" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "impostazioni" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Salva" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "Inizio" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Nome" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Default" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Valore" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Modificato" + +#~ msgid "Constance config" +#~ msgstr "Configurazione Impostazioni" diff --git a/constance/locale/pl/LC_MESSAGES/django.mo b/constance/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..3f7e0f82263bca0af4871479407d2d08aa317c24 Binary files /dev/null and b/constance/locale/pl/LC_MESSAGES/django.mo differ diff --git a/constance/locale/pl/LC_MESSAGES/django.po b/constance/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..47348bb6dd6f7c4344bd405a60ea0b9d857cee02 --- /dev/null +++ b/constance/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,97 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django-constance\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: 2014-11-27 18:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Polish (http://www.transifex.com/projects/p/django-constance/" +"language/pl/)\n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: admin.py:113 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Parametry zostały zaktualizowane" + +#: admin.py:285 +msgid "config" +msgstr "" + +#: apps.py:8 +msgid "Constance" +msgstr "" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "parametr" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "parametry" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Zapisz" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "Początek" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Nazwa" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "Domyślnie" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Wartość" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Zmodyfikowana" + +#~ msgid "Constance config" +#~ msgstr "Konfiguracja Constance" diff --git a/constance/locale/ru/LC_MESSAGES/django.mo b/constance/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..c749d6882912fbb8671876909ecefb5b09e815a1 Binary files /dev/null and b/constance/locale/ru/LC_MESSAGES/django.mo differ diff --git a/constance/locale/ru/LC_MESSAGES/django.po b/constance/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..9e1ca54c3cb62eb33284fd9b1dca397be940f433 --- /dev/null +++ b/constance/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,97 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django-constance\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: 2014-11-27 18:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Russian (http://www.transifex.com/projects/p/django-constance/" +"language/ru/)\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: admin.py:113 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "" + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "" + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "" + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "Настройки успешно сохранены" + +#: admin.py:285 +msgid "config" +msgstr "настройки" + +#: apps.py:8 +msgid "Constance" +msgstr "" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "настройки" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "настройки" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "Сохранить" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "Главная" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "Название" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "По умолчанию" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "Текущее значение" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "Было изменено" + +#~ msgid "Constance config" +#~ msgstr "Настройки" diff --git a/constance/locale/zh_CN/LC_MESSAGES/django.mo b/constance/locale/zh_CN/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..2f73cb13942a9ecf11014d188e13be78ed931a60 Binary files /dev/null and b/constance/locale/zh_CN/LC_MESSAGES/django.mo differ diff --git a/constance/locale/zh_CN/LC_MESSAGES/django.po b/constance/locale/zh_CN/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..2fa88bcc94a859946315f80f88497d48e169a75e --- /dev/null +++ b/constance/locale/zh_CN/LC_MESSAGES/django.po @@ -0,0 +1,100 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Yifu Yu , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django-constance\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-13 19:40+0530\n" +"PO-Revision-Date: 2015-03-15 18:40+0000\n" +"Last-Translator: Yifu Yu \n" +"Language-Team: Chinese (China) (http://www.transifex.com/jezdez/django-" +"constance/language/zh_CN/)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: admin.py:113 +#, fuzzy, python-format +#| msgid "" +#| "Constance doesn't support config values of the type %(config_type)s. " +#| "Please fix the value of '%(name)s'." +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "Constance不支持保存类型为%(config_type)s的值,请修正%(name)s的值。" + +#: admin.py:123 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "Constance不支持保存类型为%(config_type)s的值,请修正%(name)s的值。" + +#: admin.py:147 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "设置已经被他人修改过,请刷新页面并重新提交您的更改。" + +#: admin.py:160 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS does not contain fields that exist in " +"CONSTANCE_CONFIG." +msgstr "" + +#: admin.py:224 +msgid "Live settings updated successfully." +msgstr "成功更新实时配置" + +#: admin.py:285 +msgid "config" +msgstr "配置" + +#: apps.py:8 +msgid "Constance" +msgstr "Constance模块" + +#: backends/database/models.py:19 +msgid "constance" +msgstr "Constance模块" + +#: backends/database/models.py:20 +msgid "constances" +msgstr "Constance模块" + +#: management/commands/constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "" + +#: templates/admin/constance/change_list.html:75 +msgid "Save" +msgstr "保存" + +#: templates/admin/constance/change_list.html:84 +msgid "Home" +msgstr "首页" + +#: templates/admin/constance/includes/results_list.html:5 +msgid "Name" +msgstr "名称" + +#: templates/admin/constance/includes/results_list.html:6 +msgid "Default" +msgstr "默认值" + +#: templates/admin/constance/includes/results_list.html:7 +msgid "Value" +msgstr "值" + +#: templates/admin/constance/includes/results_list.html:8 +msgid "Is modified" +msgstr "是否修改过" + +#~ msgid "Constance config" +#~ msgstr "Constance 配置页面" diff --git a/constance/locale/zh_Hans/LC_MESSAGES/django.mo b/constance/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..f645fbce1c933883e4ff6a389931717d42add468 Binary files /dev/null and b/constance/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/constance/locale/zh_Hans/LC_MESSAGES/django.po b/constance/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000000000000000000000000000000000000..0ece168a80c0f733cf240478333673fea813824e --- /dev/null +++ b/constance/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,97 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Yifu Yu , 2015. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-04-19 11:31+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: YinKH <614457662@qq.com>\n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\admin.py:115 +#, python-format +msgid "" +"Default value type must be equal to declared config parameter type. Please " +"fix the default value of '%(name)s'." +msgstr "默认值的类型必须与参数声明类型相同,请修正%(name)s的值。" + +#: .\admin.py:125 +#, python-format +msgid "" +"Constance doesn't support config values of the type %(config_type)s. Please " +"fix the value of '%(name)s'." +msgstr "Constance不支持保存类型为%(config_type)s的值,请修正%(name)s的值。" + +#: .\admin.py:157 +msgid "" +"The settings have been modified by someone else. Please reload the form and " +"resubmit your changes." +msgstr "设置已经被他人修改过,请刷新页面并重新提交您的更改。" + +#: .\admin.py:173 +msgid "" +"CONSTANCE_CONFIG_FIELDSETS is missing field(s) that exists in " +"CONSTANCE_CONFIG." +msgstr "CONSTANCE_CONFIG_FIELDSETS中缺少在CONSTANCE_CONFIG中声明的字段。" + +#: .\admin.py:240 +msgid "Live settings updated successfully." +msgstr "实时配置更新成功" + +#: .\admin.py:301 +msgid "config" +msgstr "配置" + +#: .\backends\database\models.py:19 +msgid "constance" +msgstr "Constance模块" + +#: .\backends\database\models.py:20 +msgid "constances" +msgstr "Constance模块" + +#: .\management\commands\constance.py:30 +msgid "Get/Set In-database config settings handled by Constance" +msgstr "获取或设置由Constance模块处理的数据库配置" + +#: .\templates\admin\constance\change_list.html:60 +msgid "Save" +msgstr "保存" + +#: .\templates\admin\constance\change_list.html:69 +msgid "Home" +msgstr "首页" + +#: .\templates\admin\constance\includes\results_list.html:5 +msgid "Name" +msgstr "名称" + +#: .\templates\admin\constance\includes\results_list.html:6 +msgid "Default" +msgstr "默认值" + +#: .\templates\admin\constance\includes\results_list.html:7 +msgid "Value" +msgstr "当前值" + +#: .\templates\admin\constance\includes\results_list.html:8 +msgid "Is modified" +msgstr "是否修改过" + +#: .\templates\admin\constance\includes\results_list.html:21 +msgid "Current file" +msgstr "当前文件" + +#: .\templates\admin\constance\includes\results_list.html:36 +msgid "Reset to default" +msgstr "重置至默认值" diff --git a/constance/management/__init__.py b/constance/management/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/constance/management/commands/__init__.py b/constance/management/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/constance/management/commands/constance.py b/constance/management/commands/constance.py new file mode 100644 index 0000000000000000000000000000000000000000..0fc48f2c962d24206a810147abb0b3d965855798 --- /dev/null +++ b/constance/management/commands/constance.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.core.exceptions import ValidationError +from django.core.management import BaseCommand, CommandError +from django.utils.translation import ugettext as _ +from django import VERSION + + +from ... import config +from ...admin import ConstanceForm, get_values + + +def _set_constance_value(key, value): + """ + Parses and sets a Constance value from a string + :param key: + :param value: + :return: + """ + + form = ConstanceForm(initial=get_values()) + + field = form.fields[key] + + clean_value = field.clean(field.to_python(value)) + setattr(config, key, clean_value) + + +class Command(BaseCommand): + help = _('Get/Set In-database config settings handled by Constance') + + def add_arguments(self, parser): + subparsers = parser.add_subparsers(dest='command') + # API changed in Django>=2.1. cmd argument was removed. + parser_list = self._subparsers_add_parser(subparsers, 'list', cmd=self, help='list all Constance keys and their values') + + parser_get = self._subparsers_add_parser(subparsers, 'get', cmd=self, help='get the value of a Constance key') + parser_get.add_argument('key', help='name of the key to get', metavar='KEY') + + parser_set = self._subparsers_add_parser(subparsers, 'set', cmd=self, help='set the value of a Constance key') + parser_set.add_argument('key', help='name of the key to get', metavar='KEY') + # use nargs='+' so that we pass a list to MultiValueField (eg SplitDateTimeField) + parser_set.add_argument('value', help='value to set', metavar='VALUE', nargs='+') + + + def _subparsers_add_parser(self, subparsers, name, **kwargs): + # API in Django >= 2.1 changed and removed cmd parameter from add_parser + if VERSION >= (2, 1) and 'cmd' in kwargs: + kwargs.pop('cmd') + return subparsers.add_parser(name, **kwargs) + + + def handle(self, command, key=None, value=None, *args, **options): + + if command == 'get': + try: + self.stdout.write("{}".format(getattr(config, key)), ending="\n") + except AttributeError as e: + raise CommandError(key + " is not defined in settings.CONSTANCE_CONFIG") + + elif command == 'set': + try: + if len(value) == 1: + # assume that if a single argument was passed, the field doesn't expect a list + value = value[0] + + _set_constance_value(key, value) + except KeyError as e: + raise CommandError(key + " is not defined in settings.CONSTANCE_CONFIG") + except ValidationError as e: + raise CommandError(", ".join(e)) + + elif command == 'list': + for k, v in get_values().items(): + self.stdout.write("{}\t{}".format(k, v), ending="\n") diff --git a/constance/settings.py b/constance/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..1c597e246590def8552865c5705e773776fb940c --- /dev/null +++ b/constance/settings.py @@ -0,0 +1,45 @@ +from django.conf import settings + +BACKEND = getattr( + settings, + 'CONSTANCE_BACKEND', + 'constance.backends.redisd.RedisBackend' +) + +CONFIG = getattr(settings, 'CONSTANCE_CONFIG', {}) + +CONFIG_FIELDSETS = getattr(settings, 'CONSTANCE_CONFIG_FIELDSETS', {}) + +ADDITIONAL_FIELDS = getattr(settings, 'CONSTANCE_ADDITIONAL_FIELDS', {}) + +DATABASE_CACHE_BACKEND = getattr( + settings, + 'CONSTANCE_DATABASE_CACHE_BACKEND', + None +) + +DATABASE_CACHE_AUTOFILL_TIMEOUT = getattr( + settings, + 'CONSTANCE_DATABASE_CACHE_AUTOFILL_TIMEOUT', + 60 * 60 * 24 +) + +DATABASE_PREFIX = getattr(settings, 'CONSTANCE_DATABASE_PREFIX', '') + +REDIS_PREFIX = getattr(settings, 'CONSTANCE_REDIS_PREFIX', 'constance:') + +REDIS_CONNECTION_CLASS = getattr( + settings, + 'CONSTANCE_REDIS_CONNECTION_CLASS', + None +) + +REDIS_CONNECTION = getattr(settings, 'CONSTANCE_REDIS_CONNECTION', {}) + +SUPERUSER_ONLY = getattr(settings, 'CONSTANCE_SUPERUSER_ONLY', True) + +IGNORE_ADMIN_VERSION_CHECK = getattr( + settings, + 'CONSTANCE_IGNORE_ADMIN_VERSION_CHECK', + False +) diff --git a/constance/signals.py b/constance/signals.py new file mode 100644 index 0000000000000000000000000000000000000000..f0c9796164297f916e28de6f8151a68993be3901 --- /dev/null +++ b/constance/signals.py @@ -0,0 +1,5 @@ +import django.dispatch + +config_updated = django.dispatch.Signal( + providing_args=['key', 'old_value', 'new_value'] +) diff --git a/constance/static/admin/css/constance.css b/constance/static/admin/css/constance.css new file mode 100644 index 0000000000000000000000000000000000000000..4d74660f4431e35de74f1c1b2b78198ef0496286 --- /dev/null +++ b/constance/static/admin/css/constance.css @@ -0,0 +1,15 @@ +#result_list .changed { + background-color: #ffc; +} +#changelist table thead th .text { + padding: 2px 5px; +} +#changelist table tbody td:first-child { + text-align: left; +} +#changelist-form ul.errorlist { + margin: 0 !important; +} +.help { + font-weight: normal !important; +} diff --git a/constance/static/admin/js/constance.js b/constance/static/admin/js/constance.js new file mode 100644 index 0000000000000000000000000000000000000000..690dfccaffe7953b0c58f1bae51b13270ce49889 --- /dev/null +++ b/constance/static/admin/js/constance.js @@ -0,0 +1,26 @@ +(function($) { + 'use strict'; + + $(function() { + + $('#content-main').on('click', '.reset-link', function(e) { + e.preventDefault(); + + var field = $('#' + this.dataset.fieldId); + var fieldType = this.dataset.fieldType; + + if (fieldType === 'checkbox') { + field.prop('checked', this.dataset.default === 'true'); + } else if (fieldType === 'date') { + var defaultDate = new Date(this.dataset.default * 1000); + $('#' + this.dataset.fieldId).val(defaultDate.strftime(get_format('DATE_INPUT_FORMATS')[0]));} + } else if (fieldType === 'datetime') { + var defaultDate = new Date(this.dataset.default * 1000); + $('#' + this.dataset.fieldId + '_0').val(defaultDate.strftime(get_format('DATE_INPUT_FORMATS')[0])); + $('#' + this.dataset.fieldId + '_1').val(defaultDate.strftime(get_format('TIME_INPUT_FORMATS')[0])); + } else { + field.val(this.dataset.default); + } + }); + }); +})(django.jQuery); diff --git a/constance/templates/admin/constance/change_list.html b/constance/templates/admin/constance/change_list.html new file mode 100644 index 0000000000000000000000000000000000000000..bdee4d2ece5f864bb605f8867dcf1d8e5061dfef --- /dev/null +++ b/constance/templates/admin/constance/change_list.html @@ -0,0 +1,73 @@ +{% extends "admin/base_site.html" %} +{% load admin_static admin_list i18n %} + +{% block extrastyle %} + {{ block.super }} + + + {{ media.css }} + +{% endblock %} + +{% block extrahead %} +{% url 'admin:jsi18n' as jsi18nurl %} + +{{ block.super }} +{{ media.js }} + +{% endblock %} + +{% block bodyclass %}change-list{% endblock %} + +{% block content %} +
+
+
{% csrf_token %} + {% if form.non_field_errors %} +
    + {% for error in form.non_field_errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} + {% if form.errors %} +
    + {% endif %} + {% for field in form.hidden_fields %} + {% for error in field.errors %} +
  • {{ error }}
  • + {% endfor %} + {{ field }} + {% endfor %} + {% if form.errors %} +
+ {% endif %} + + {% if fieldsets %} + {% for fieldset in fieldsets %} +
+

{{ fieldset.title }}

+ {% with config_values=fieldset.config_values %} + {% include "admin/constance/includes/../../../../venv/Lib/site-packages/constance/templates/admin/constance/includes/results_list.html" %} + {% endwith %} +
+ {% endfor %} + {% else %} + {% include "admin/constance/includes/../../../../venv/Lib/site-packages/constance/templates/admin/constance/includes/results_list.html" %} + {% endif %} + +

+ +

+
+
+
+{% endblock %} + +{% block breadcrumbs %} + +{% endblock %} diff --git a/constance/templates/admin/constance/includes/results_list.html b/constance/templates/admin/constance/includes/results_list.html new file mode 100644 index 0000000000000000000000000000000000000000..295388be2a40268acb5a09dc96a25baf6e5fd2dc --- /dev/null +++ b/constance/templates/admin/constance/includes/results_list.html @@ -0,0 +1,49 @@ +{% load admin_static admin_list static i18n %} + + + + + + + + + + {% for item in config_values %} + + + + + + + {% endfor %} +
{% trans "Name" %}
{% trans "Default" %}
{% trans "Value" %}
{% trans "Is modified" %}
+ {{ item.name }}
{{ item.help_text|linebreaksbr }}
+
+ {{ item.default|linebreaks }} + + {{ item.form_field.errors }} + {% if item.is_file %}{% trans "Current file" %}: {{ item.value }}{% endif %} + {{ item.form_field }} +
+ {% trans "Reset to default" %} +
+ {% if item.modified %} + {{ item.modified }} + {% else %} + {{ item.modified }} + {% endif %} +
diff --git a/constance/test/__init__.py b/constance/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0fb5524c914df08cf322a8d94fe2c33f01861029 --- /dev/null +++ b/constance/test/__init__.py @@ -0,0 +1 @@ +from .utils import override_config diff --git a/constance/test/utils.py b/constance/test/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..eff0abdd959177808ac6236f8b66f3f01b8d5e00 --- /dev/null +++ b/constance/test/utils.py @@ -0,0 +1,85 @@ +from functools import wraps + +from django.test import SimpleTestCase +from django.test.utils import override_settings + +from .. import config + +__all__ = ('override_config',) + + +class override_config(override_settings): + """ + Decorator to modify constance setting for TestCase. + + Based on django.test.utils.override_settings. + """ + def __init__(self, **kwargs): + super(override_config, self).__init__(**kwargs) + self.original_values = {} + + def __call__(self, test_func): + """ + Modify the decorated function to override config values. + """ + if isinstance(test_func, type): + if not issubclass(test_func, SimpleTestCase): + raise Exception( + "Only subclasses of Django SimpleTestCase can be " + "decorated with override_config") + return self.modify_test_case(test_func) + else: + @wraps(test_func) + def inner(*args, **kwargs): + with self: + return test_func(*args, **kwargs) + return inner + + def modify_test_case(self, test_case): + """ + Override the config by modifying TestCase methods. + + This method follows the Django <= 1.6 method of overriding the + _pre_setup and _post_teardown hooks rather than modifying the TestCase + itself. + """ + original_pre_setup = test_case._pre_setup + original_post_teardown = test_case._post_teardown + + def _pre_setup(inner_self): + self.enable() + original_pre_setup(inner_self) + + def _post_teardown(inner_self): + original_post_teardown(inner_self) + self.disable() + + test_case._pre_setup = _pre_setup + test_case._post_teardown = _post_teardown + + return test_case + + def enable(self): + """ + Store original config values and set overridden values. + """ + # Store the original values to an instance variable + for config_key in self.options: + self.original_values[config_key] = getattr(config, config_key) + + # Update config with the overriden values + self.unpack_values(self.options) + + def disable(self): + """ + Set original values to the config. + """ + self.unpack_values(self.original_values) + + @staticmethod + def unpack_values(options): + """ + Unpack values from the given dict to config. + """ + for name, value in options.items(): + setattr(config, name, value) diff --git a/constance/utils.py b/constance/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..8d8d3419cf99d04b4910d9db2fdb92934c20fc40 --- /dev/null +++ b/constance/utils.py @@ -0,0 +1,6 @@ +from importlib import import_module + + +def import_module_attr(path): + package, module = path.rsplit('.', 1) + return getattr(import_module(package), module) diff --git a/requirements.txt b/requirements.txt index a6d4ac485298cde307446f7b8c950b3a9561bd6e..b2ffc6f9773889f9d0e168dd79cb199cdc228ece 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -Django>=1.10,<2.1 ; python_version >= '3.4' +Django>=1.10; python_version >= '3.4' Pillow>=2.9.0 apscheduler>=3.3.0 -django-constance[database]>=2.1 +#django-constance[database]>=2.1 lxml python-telegram-bot>=10