Simple app to add configuration options to a Django project.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor and improvements

+131 -64
+5
AUTHORS.rst
··· 6 6 ---------------- 7 7 8 8 * Marcos Gabarda <hey@marcosgabarda.com> 9 + 10 + Contributors 11 + ------------ 12 + 13 + * Antoni Aloy
+7
HISTORY.rst
··· 3 3 History 4 4 ------- 5 5 6 + 1.1 (2019-07-01) 7 + +++++++++++++++++ 8 + 9 + * Added validation on types before saving (Thanks to @aaloy!) 10 + * 11 + 12 + 6 13 1.0 (2018-10-2) 7 14 +++++++++++++++++ 8 15
+2 -2
options/__init__.py
··· 1 - # -*- coding: utf-8 -*- 2 - 1 + import six 3 2 from django import get_version 4 3 from django.utils.translation import ugettext_lazy as _ 5 4 6 5 7 6 FLOAT, INT, STRING = (0, 1, 2) 8 7 TYPE_CHOICES = ((FLOAT, _("Float")), (INT, _("Integer")), (STRING, _("String"))) 8 + CONVERTER = {INT: int, FLOAT: float, STRING: six.text_type} 9 9 10 10 default_app_config = "options.apps.ConfigurationsConfig" 11 11
-2
options/admin.py
··· 1 - # -*- coding: utf-8 -*- 2 - 3 1 from django.contrib import admin 4 2 from options.models import Option 5 3
-1
options/apps.py
··· 1 - # -*- coding: utf-8 -*- 2 1 import logging 3 2 import six 4 3 from django.apps import AppConfig
-1
options/context_processors.py
··· 1 - # -*- coding: utf-8 -*- 2 1 from options.models import Option 3 2 4 3
+13
options/helpers.py
··· 1 + import six 2 + 3 + from options import INT, FLOAT, STRING, CONVERTER 4 + 5 + 6 + def convert_value(value, value_type): 7 + """Converts the given value to the given type.""" 8 + default_values = {INT: 0, FLOAT: 1.0, STRING: ""} 9 + try: 10 + option_value = CONVERTER.get(value_type, six.text_type)(value) 11 + except ValueError: 12 + option_value = default_values.get(value_type) 13 + return option_value
-2
options/management/__init__.py
··· 1 - # -*- coding: utf-8 -*- 2 - from __future__ import unicode_literals, print_function, division, absolute_import
-2
options/management/commands/__init__.py
··· 1 - # -*- coding: utf-8 -*- 2 - from __future__ import unicode_literals, print_function, division, absolute_import
-1
options/management/commands/export_options.py
··· 1 - # -*- coding: utf-8 -*- 2 1 import json 3 2 4 3 from django.core.management import BaseCommand
-3
options/managers.py
··· 1 - # -*- coding: utf-8 -*- 2 - 3 - 4 1 from django.db import models 5 2 from options.settings import DEFAULT_EXCLUDE_USER_OPTIONS 6 3
+46 -10
options/migrations/0001_initial.py
··· 9 9 10 10 initial = True 11 11 12 - dependencies = [ 13 - ] 12 + dependencies = [] 14 13 15 14 operations = [ 16 15 migrations.CreateModel( 17 - name='Option', 16 + name="Option", 18 17 fields=[ 19 - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 - ('name', models.CharField(db_index=True, max_length=255, unique=True, verbose_name='Parameter')), 21 - ('public_name', models.CharField(db_index=True, max_length=255, verbose_name='Public name of the parameter')), 22 - ('type', models.PositiveIntegerField(choices=[(0, 'Float'), (1, 'Integer'), (2, 'String')], default=2)), 23 - ('value', models.CharField(blank=True, default=None, max_length=256, null=True, verbose_name='Value')), 24 - ('is_list', models.BooleanField(default=False)), 18 + ( 19 + "id", 20 + models.AutoField( 21 + auto_created=True, 22 + primary_key=True, 23 + serialize=False, 24 + verbose_name="ID", 25 + ), 26 + ), 27 + ( 28 + "name", 29 + models.CharField( 30 + db_index=True, 31 + max_length=255, 32 + unique=True, 33 + verbose_name="Parameter", 34 + ), 35 + ), 36 + ( 37 + "public_name", 38 + models.CharField( 39 + db_index=True, 40 + max_length=255, 41 + verbose_name="Public name of the parameter", 42 + ), 43 + ), 44 + ( 45 + "type", 46 + models.PositiveIntegerField( 47 + choices=[(0, "Float"), (1, "Integer"), (2, "String")], default=2 48 + ), 49 + ), 50 + ( 51 + "value", 52 + models.CharField( 53 + blank=True, 54 + default=None, 55 + max_length=256, 56 + null=True, 57 + verbose_name="Value", 58 + ), 59 + ), 60 + ("is_list", models.BooleanField(default=False)), 25 61 ], 26 - ), 62 + ) 27 63 ]
+48 -16
options/migrations/0002_auto_20181002_0254.py
··· 9 9 10 10 dependencies = [ 11 11 migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 - ('options', '0001_initial'), 12 + ("options", "0001_initial"), 13 13 ] 14 14 15 15 operations = [ 16 16 migrations.CreateModel( 17 - name='UserOption', 17 + name="UserOption", 18 18 fields=[ 19 - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 - ('public_name', models.CharField(db_index=True, max_length=255, verbose_name='Public name of the parameter')), 21 - ('type', models.PositiveIntegerField(choices=[(0, 'Float'), (1, 'Integer'), (2, 'String')], default=2)), 22 - ('value', models.CharField(blank=True, default=None, max_length=256, null=True, verbose_name='Value')), 23 - ('is_list', models.BooleanField(default=False)), 24 - ('name', models.CharField(max_length=255, verbose_name='Parameter')), 25 - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='options', to=settings.AUTH_USER_MODEL)), 19 + ( 20 + "id", 21 + models.AutoField( 22 + auto_created=True, 23 + primary_key=True, 24 + serialize=False, 25 + verbose_name="ID", 26 + ), 27 + ), 28 + ( 29 + "public_name", 30 + models.CharField( 31 + db_index=True, 32 + max_length=255, 33 + verbose_name="Public name of the parameter", 34 + ), 35 + ), 36 + ( 37 + "type", 38 + models.PositiveIntegerField( 39 + choices=[(0, "Float"), (1, "Integer"), (2, "String")], default=2 40 + ), 41 + ), 42 + ( 43 + "value", 44 + models.CharField( 45 + blank=True, 46 + default=None, 47 + max_length=256, 48 + null=True, 49 + verbose_name="Value", 50 + ), 51 + ), 52 + ("is_list", models.BooleanField(default=False)), 53 + ("name", models.CharField(max_length=255, verbose_name="Parameter")), 54 + ( 55 + "user", 56 + models.ForeignKey( 57 + on_delete=django.db.models.deletion.CASCADE, 58 + related_name="options", 59 + to=settings.AUTH_USER_MODEL, 60 + ), 61 + ), 26 62 ], 27 - options={ 28 - 'ordering': ['public_name'], 29 - }, 63 + options={"ordering": ["public_name"]}, 30 64 ), 31 65 migrations.AlterModelOptions( 32 - name='option', 33 - options={'ordering': ['public_name']}, 66 + name="option", options={"ordering": ["public_name"]} 34 67 ), 35 68 migrations.AlterUniqueTogether( 36 - name='useroption', 37 - unique_together={('user', 'name')}, 69 + name="useroption", unique_together={("user", "name")} 38 70 ), 39 71 ]
+9 -19
options/models.py
··· 1 - # -*- coding: utf-8 -*- 2 - 3 - 4 1 import six 5 2 from django.conf import settings 3 + from django.core.exceptions import ValidationError 6 4 from django.db import models 7 5 from django.utils.translation import ugettext_lazy as _ 8 6 9 - from options import STRING, TYPE_CHOICES, INT, FLOAT 7 + from options import STRING, TYPE_CHOICES, CONVERTER 8 + from options.helpers import convert_value 10 9 from options.managers import OptionManager, UserOptionManager 11 10 12 11 ··· 34 33 def __str__(self): 35 34 return "%s" % self.public_name 36 35 37 - def _convert_value(self, value, type): 38 - converter = {INT: int, FLOAT: float, STRING: six.text_type} 39 - default_values = {INT: 0, FLOAT: 1.0, STRING: ""} 40 - try: 41 - option_value = converter.get(self.type, six.text_type)(self.value) 42 - except ValueError: 43 - option_value = default_values.get(self.type) 44 - return option_value 45 - 46 36 def get_value(self): 47 37 """Gets the value with the proper type. If the type is not 48 38 valid it would return the default value for the field, to avoid 49 39 problems with manual database modifications""" 50 40 51 41 if not self.is_list: 52 - return self._convert_value(self.value, self.type) 42 + return convert_value(self.value, self.type) 53 43 else: 54 44 values = self.value.split(",") 55 - return [self._convert_value(self.type, item) for item in values] 45 + return [convert_value(self.type, value) for value in values] 56 46 57 47 def clean(self): 58 - from django.core.exceptions import ValidationError 59 - 60 - converter = {INT: int, FLOAT: float, STRING: six.text_type} 48 + """Calls to the converter to check the type conversion. Added exception 49 + for lists, to check all values.""" 61 50 try: 62 - converter.get(self.type, six.text_type)(self.value) 51 + values = [self.value] if not self.is_list else self.value.split(",") 52 + [CONVERTER.get(self.type, six.text_type)(value) for value in values] 63 53 except ValueError: 64 54 raise ValidationError(_("Invalid value for this type.")) 65 55
+1 -5
options/settings.py
··· 1 - # -*- coding: utf-8 -*- 2 - from __future__ import unicode_literals, print_function, division, absolute_import 3 - 4 1 from django.conf import settings 5 - 6 2 7 3 # Set on settings the default options for this project. These will be created 8 4 # on the post migrate signal handler. ··· 19 15 DEFAULT_OPTIONS = getattr(settings, "CONFIGURATION_DEFAULT_OPTIONS", {}) 20 16 21 17 # Set the list of options that the user can't customize. 22 - DEFAULT_EXCLUDE_USER_OPTIONS = getattr(settings, "EXCLUDE_USER_OPTIONS", tuple()) 18 + DEFAULT_EXCLUDE_USER_OPTIONS = getattr(settings, "EXCLUDE_USER_OPTIONS", tuple())