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.

fist commit

Marcos Gabarda c646b330

+480
+62
.gitignore
··· 1 + ## OSX ### 2 + .DS_Store 3 + .AppleDouble 4 + .LSOverride 5 + 6 + ### SublimeText ### 7 + # cache files for sublime text 8 + *.tmlanguage.cache 9 + *.tmPreferences.cache 10 + *.stTheme.cache 11 + 12 + # workspace files are user-specific 13 + *.sublime-workspace 14 + 15 + # project files should be checked into the repository, unless a significant 16 + # proportion of contributors will probably not be using SublimeText 17 + # *.sublime-project 18 + 19 + # sftp configuration file 20 + sftp-config.json 21 + 22 + # Basics 23 + *.py[cod] 24 + __pycache__ 25 + 26 + # Packaging files: 27 + *.egg* 28 + 29 + # Logs 30 + logs 31 + *.log 32 + pip-log.txt 33 + 34 + # Unit test / coverage reports 35 + .cache 36 + .coverage 37 + .tox 38 + nosetests.xml 39 + htmlcov 40 + 41 + # Translations 42 + *.mo 43 + *.pot 44 + 45 + # Pycharm 46 + .idea 47 + 48 + # Vim 49 + 50 + *~ 51 + *.swp 52 + *.swo 53 + 54 + 55 + # virtual environments 56 + .env 57 + 58 + # Others 59 + docs/_build 60 + build/ 61 + dist/ 62 + .coverage
+8
AUTHORS.rst
··· 1 + ======= 2 + Credits 3 + ======= 4 + 5 + Development Lead 6 + ---------------- 7 + 8 + * Marcos Gabarda <hey@marcosgabarda.com>
+9
HISTORY.rst
··· 1 + .. :changelog: 2 + 3 + History 4 + ------- 5 + 6 + 1.0a1 (2017-2-20) 7 + +++++++++++++++++ 8 + 9 + * First release on PyPI.
+21
LICENSE
··· 1 + The MIT License (MIT) 2 + 3 + Copyright (c) 2017 Marcos Gabarda 4 + 5 + Permission is hereby granted, free of charge, to any person obtaining a copy 6 + of this software and associated documentation files (the "Software"), to deal 7 + in the Software without restriction, including without limitation the rights 8 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 + copies of the Software, and to permit persons to whom the Software is 10 + furnished to do so, subject to the following conditions: 11 + 12 + The above copyright notice and this permission notice shall be included in 13 + all copies or substantial portions of the Software. 14 + 15 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 + THE SOFTWARE.
+3
MANIFEST.in
··· 1 + include LICENSE 2 + include README.rst 3 + include HISTORY.rst
+30
README.rst
··· 1 + ============== 2 + Django Options 3 + ============== 4 + 5 + Simple app to add configuration options to a Django project. 6 + 7 + Quick start 8 + ----------- 9 + 10 + **1** Install using pip:: 11 + 12 + $ pip install django-options 13 + 14 + **2** Add "options" to your INSTALLED_APPS settings like this:: 15 + 16 + INSTALLED_APPS += ('options',) 17 + 18 + 19 + Settings options 20 + ---------------- 21 + 22 + Use ``CONFIGURATION_DEFAULT_OPTIONS`` to set the default options:: 23 + 24 + CONFIGURATION_DEFAULT_OPTIONS = { 25 + "sold_out": { 26 + "value": 0, 27 + "type": INT, 28 + "public_name": "Sets tickets as sold out" 29 + }, 30 + }
+12
manage.py
··· 1 + #!/usr/bin/env python 2 + # -*- coding: utf-8 -*- 3 + from __future__ import unicode_literals, absolute_import 4 + 5 + import os 6 + import sys 7 + 8 + if __name__ == "__main__": 9 + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings") 10 + from django.core.management import execute_from_command_line 11 + 12 + execute_from_command_line(sys.argv)
+19
options/__init__.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import 3 + 4 + from django import get_version 5 + from django.utils.translation import ugettext_lazy as _ 6 + 7 + 8 + FLOAT, INT, STRING = (0, 1, 2) 9 + TYPE_CHOICES = ( 10 + (FLOAT, _("Float")), 11 + (INT, _("Integer")), 12 + (STRING, _("String")), 13 + ) 14 + 15 + default_app_config = 'options.apps.ConfigurationsConfig' 16 + 17 + VERSION = (1, 0, 0, 'alpha', 1) 18 + 19 + __version__ = get_version(VERSION)
+13
options/admin.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, absolute_import 3 + 4 + from django.contrib import admin 5 + 6 + from options.models import Option 7 + 8 + 9 + @admin.register(Option) 10 + class OptionAdmin(admin.ModelAdmin): 11 + """Manage configuration options.""" 12 + 13 + list_display = ['public_name', 'value']
+31
options/apps.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import 3 + 4 + import logging 5 + import six 6 + from django.apps import AppConfig 7 + from django.db.models.signals import post_migrate 8 + from django.db.utils import IntegrityError 9 + 10 + from options.settings import DEFAULT_OPTIONS 11 + 12 + logger = logging.getLogger(__name__) 13 + 14 + 15 + def create_default_options(sender, **kwargs): 16 + """Creates the defaults configuration options if they don't exists.""" 17 + from options.models import Option 18 + for key, data in six.iteritems(DEFAULT_OPTIONS): 19 + if not Option.objects.filter(name=key).exists(): 20 + try: 21 + Option.objects.create(name=key, **data) 22 + except IntegrityError: 23 + logger.warning("Option '%s' already installed" % key) 24 + 25 + 26 + class ConfigurationsConfig(AppConfig): 27 + name = "options" 28 + 29 + def ready(self): 30 + """Connects signals with their managers.""" 31 + post_migrate.connect(create_default_options)
+9
options/context_processors.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, absolute_import 3 + 4 + from options.models import Option 5 + 6 + 7 + def options(request): 8 + """Context processor that adds options to the template context.""" 9 + return {option.name: option.get_value() for option in Option.objects.all()}
+17
options/managers.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import 3 + 4 + from django.db import models 5 + 6 + 7 + class OptionManager(models.Manager): 8 + """Manager for options.""" 9 + 10 + def get_value(self, name, default=None): 11 + """Gets the value with the proper type.""" 12 + try: 13 + option = self.model.objects.get(name=name) 14 + return option.get_value() 15 + except self.model.DoesNotExist: 16 + return default 17 +
+27
options/migrations/0001_initial.py
··· 1 + # -*- coding: utf-8 -*- 2 + # Generated by Django 1.10.5 on 2017-02-23 15:53 3 + from __future__ import unicode_literals 4 + 5 + from django.db import migrations, models 6 + 7 + 8 + class Migration(migrations.Migration): 9 + 10 + initial = True 11 + 12 + dependencies = [ 13 + ] 14 + 15 + operations = [ 16 + migrations.CreateModel( 17 + name='Option', 18 + 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)), 25 + ], 26 + ), 27 + ]
options/migrations/__init__.py

This is a binary file and will not be displayed.

+59
options/models.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import 3 + 4 + import six 5 + from django.contrib.gis.db import models 6 + from django.utils.encoding import python_2_unicode_compatible 7 + from django.utils.translation import ugettext_lazy as _ 8 + 9 + from options import STRING, TYPE_CHOICES, INT, FLOAT 10 + from options.managers import OptionManager 11 + 12 + 13 + @python_2_unicode_compatible 14 + class Option(models.Model): 15 + """System options and configurations.""" 16 + 17 + name = models.CharField( 18 + verbose_name=_("Parameter"), 19 + max_length=255, 20 + unique=True, 21 + db_index=True 22 + ) 23 + public_name = models.CharField( 24 + verbose_name=_("Public name of the parameter"), 25 + max_length=255, 26 + unique=False, 27 + db_index=True 28 + ) 29 + type = models.PositiveIntegerField( 30 + choices=TYPE_CHOICES, 31 + default=STRING 32 + ) 33 + value = models.CharField( 34 + null=True, 35 + blank=True, 36 + default=None, 37 + max_length=256, 38 + verbose_name=_("Value") 39 + ) 40 + 41 + is_list = models.BooleanField(default=False) 42 + 43 + objects = OptionManager() 44 + 45 + def __str__(self): 46 + return "%s" % self.public_name 47 + 48 + def get_value(self): 49 + """Gets the value with the proper type.""" 50 + converter = { 51 + INT: int, 52 + FLOAT: float, 53 + STRING: six.text_type 54 + } 55 + if not self.is_list: 56 + return converter.get(self.type, six.text_type)(self.value) 57 + else: 58 + values = self.value.split(",") 59 + return list(map(lambda item: converter.get(self.type, six.text_type)(item), values))
+19
options/settings.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import 3 + 4 + from django.conf import settings 5 + 6 + 7 + # Set on settings the default options for this project. These will be created 8 + # on the post migrate signal handler. 9 + # Sample: 10 + # 11 + # CONFIGURATION_DEFAULT_OPTIONS = { 12 + # "sold_out": { 13 + # "value": 0, 14 + # "type": INT, 15 + # "public_name": "Sets tickets as sold out" 16 + # }, 17 + # } 18 + # 19 + DEFAULT_OPTIONS = getattr(settings, "CONFIGURATION_DEFAULT_OPTIONS", {})
+2
requirements.txt
··· 1 + django>=1.9 2 + six>=1.0
+6
requirements_test.txt
··· 1 + coverage==4.3.4 2 + mock>=1.0.1 3 + flake8>=2.1.0 4 + tox>=1.7.0 5 + codecov>=2.0.0 6 + six>=1.0
+26
runtests.py
··· 1 + #!/usr/bin/env python 2 + # -*- coding: utf-8 3 + from __future__ import unicode_literals, absolute_import 4 + 5 + import os 6 + import sys 7 + 8 + import django 9 + from django.conf import settings 10 + from django.test.utils import get_runner 11 + 12 + 13 + def run_tests(*test_args): 14 + if not test_args: 15 + test_args = ['tests'] 16 + 17 + os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings' 18 + django.setup() 19 + TestRunner = get_runner(settings) 20 + test_runner = TestRunner() 21 + failures = test_runner.run_tests(test_args) 22 + sys.exit(bool(failures)) 23 + 24 + 25 + if __name__ == '__main__': 26 + run_tests(*sys.argv[1:])
+5
setup.cfg
··· 1 + [metadata] 2 + description-file = README.rst 3 + 4 + [wheel] 5 + universal=1
+51
setup.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import 3 + 4 + import os 5 + 6 + from setuptools import setup 7 + 8 + with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme: 9 + README = readme.read() 10 + 11 + with open(os.path.join(os.path.dirname(__file__), 'HISTORY.rst')) as history: 12 + HISTORY = history.read().replace('.. :changelog:', '') 13 + 14 + # Allow setup.py to be run from any path 15 + os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) 16 + 17 + # Dynamically calculate the version based on belt.VERSION. 18 + version = __import__('options').__version__ 19 + 20 + 21 + setup( 22 + name='django-options', 23 + version=version, 24 + packages=[ 25 + 'options.migrations', 26 + 'options', 27 + ], 28 + include_package_data=True, 29 + license='MIT License', 30 + description='Simple app to add configuration options to a Django project', 31 + long_description=README + '\n\n' + HISTORY, 32 + url='https://github.com/marcosgabarda/django-options', 33 + author='Marcos Gabarda', 34 + author_email='hey@marcosgabarda.com', 35 + classifiers=[ 36 + 'Development Status :: 3 - Alpha', 37 + 'Environment :: Web Environment', 38 + 'Framework :: Django', 39 + 'Intended Audience :: Developers', 40 + 'License :: OSI Approved :: MIT License', 41 + 'Operating System :: OS Independent', 42 + 'Programming Language :: Python', 43 + 'Programming Language :: Python :: 2', 44 + 'Programming Language :: Python :: 3', 45 + 'Topic :: Utilities', 46 + ], 47 + install_requires=[ 48 + 'django>=1.9', 49 + 'six>=1.0', 50 + ], 51 + )
+2
tests/__init__.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, print_function, division, absolute_import
+30
tests/settings.py
··· 1 + # -*- coding: utf-8 -*- 2 + from __future__ import unicode_literals, absolute_import 3 + 4 + import django 5 + 6 + DEBUG = True 7 + USE_TZ = True 8 + 9 + SECRET_KEY = "dummy" 10 + 11 + DATABASES = { 12 + "default": { 13 + "ENGINE": "django.db.backends.sqlite3", 14 + "NAME": ":memory:", 15 + } 16 + } 17 + 18 + INSTALLED_APPS = [ 19 + "django.contrib.auth", 20 + "django.contrib.contenttypes", 21 + "django.contrib.sites", 22 + "options", 23 + ] 24 + 25 + SITE_ID = 1 26 + 27 + if django.VERSION >= (1, 10): 28 + MIDDLEWARE = () 29 + else: 30 + MIDDLEWARE_CLASSES = ()
+19
tox.ini
··· 1 + [tox] 2 + envlist = 3 + {py27,py36}-django-19 4 + {py27,py36}-django-110 5 + 6 + [testenv] 7 + setenv = 8 + PYTHONPATH = {toxinidir}:{toxinidir}/gis_timezones 9 + 10 + commands = coverage run --source gis_timezones runtests.py 11 + 12 + deps = 13 + django-19: Django>=1.9,<1.10 14 + django-110: Django>=1.10 15 + -r{toxinidir}/requirements_test.txt 16 + 17 + basepython = 18 + py36: python3.6 19 + py27: python2.7