mirror of
https://github.com/jazzband/django-constance.git
synced 2026-03-16 22:40:24 +00:00
Merge remote-tracking branch 'jezdez/master' into custom_fields
This commit is contained in:
commit
55ddbad52c
24 changed files with 373 additions and 116 deletions
28
.travis.yml
28
.travis.yml
|
|
@ -1,31 +1,21 @@
|
|||
sudo: false
|
||||
language: python
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/pip
|
||||
install:
|
||||
- pip install tox
|
||||
env:
|
||||
- TOXENV=py26-django-14
|
||||
- TOXENV=py27-django-14
|
||||
- TOXENV=py26-django-15
|
||||
- TOXENV=py26-django-16
|
||||
- TOXENV=py27-django-15
|
||||
- TOXENV=py27-django-16
|
||||
- TOXENV=py32-django-15
|
||||
- TOXENV=py32-django-16
|
||||
- TOXENV=py33-django-15
|
||||
- TOXENV=py33-django-16
|
||||
- TOXENV=py34-django-15
|
||||
- TOXENV=py34-django-16
|
||||
- TOXENV=pypy-django-15
|
||||
- TOXENV=pypy-django-16
|
||||
- TOXENV=py27-django-17
|
||||
- TOXENV=py27-django-master
|
||||
- TOXENV=py32-django-17
|
||||
- TOXENV=py32-django-master
|
||||
- TOXENV=py27-django-18
|
||||
- TOXENV=py33-django-17
|
||||
- TOXENV=py33-django-master
|
||||
- TOXENV=py33-django-18
|
||||
- TOXENV=py34-django-17
|
||||
- TOXENV=py34-django-master
|
||||
- TOXENV=py34-django-18
|
||||
- TOXENV=pypy-django-17
|
||||
- TOXENV=pypy-django-18
|
||||
- TOXENV=py27-django-master
|
||||
- TOXENV=py34-django-master
|
||||
- TOXENV=pypy-django-master
|
||||
script:
|
||||
- tox
|
||||
|
|
|
|||
42
AUTHORS
42
AUTHORS
|
|
@ -1,7 +1,39 @@
|
|||
Jiri Barton <jbar@hosting4u.cz>
|
||||
Vojtech Jasny <voy@voy.cz>
|
||||
Roman Krejcik <farin@farin.cz>
|
||||
Jan Vesely <jave@janvesely.com>
|
||||
Ales Zoulek <ales.zoulek@gmail.com>
|
||||
Jannis Leidel <jannis@leidel.info>
|
||||
Alexander frenzel <alex@relatedworks.com>
|
||||
Bouke Haarsma <bouke@webatoom.nl>
|
||||
Camilo Nova <camilo.nova@gmail.com>
|
||||
Charlie Hornsby <charlie.hornsby@hotmail.co.uk>
|
||||
Curtis Maloney <curtis@tinbrain.net>
|
||||
Dan Poirier <dpoirier@caktusgroup.com>
|
||||
David Burke <dmbst32@gmail.com>
|
||||
Florian Apolloner <florian@apolloner.eu>
|
||||
Igor Támara <igor@axiacore.com>
|
||||
Jake Merdich <jmerdich@users.noreply.github.com>
|
||||
Jannis Leidel <jannis@leidel.info>
|
||||
Janusz Harkot <janusz.harkot@gmail.com>
|
||||
Jiri Barton <jbar@hosting4u.cz>
|
||||
Jonas <jvp@jonasundderwolf.de>
|
||||
Kuba Zarzycki <jakubzarzycki@gmail.com>
|
||||
Leandra Finger <leandra.finger@gmail.com>
|
||||
Les Orchard <me@lmorchard.com>
|
||||
Lin Xianyi <iynaix@gmail.com>
|
||||
Marcin Baran <marcin.baran@agencjawmc.pl>
|
||||
Mario Orlandi <morlandi@brainstorm.it>
|
||||
Mario Rosa <mario@dwaiter.com>
|
||||
Mattia Larentis <mattia@larentis.eu>
|
||||
Merijn Bertels <merijn.bertels@gmail.com>
|
||||
Omer Katz <omer.drow@gmail.com>
|
||||
Petr Knap <dev@petrknap.cz>
|
||||
Philip Neustrom <philipn@gmail.com>
|
||||
Pierre-Olivier Marec <pomarec@free.fr>
|
||||
Roman Krejcik <farin@farin.cz>
|
||||
Silvan Spross <silvan.spross@gmail.com>
|
||||
Sławek Ehlert <slafs@op.pl>
|
||||
Vojtech Jasny <voy@voy.cz>
|
||||
Yin Jifeng <jifeng.yin@gmail.com>
|
||||
illumin-us-r3v0lution <luminaries@riseup.net>
|
||||
mega <qoisone@gmail.com>
|
||||
saw2th <stephen@saw2th.co.uk>
|
||||
trbs <trbs@trbs.net>
|
||||
vl <1844144@gmail.com>
|
||||
vl <vl@u64.(none)>
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2009-2014, Comoga and individual contributors
|
||||
Copyright (c) 2009-2015, Comoga and individual contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from django.utils.functional import LazyObject
|
||||
|
||||
__version__ = '1.0.1'
|
||||
__version__ = '1.1.1'
|
||||
|
||||
default_app_config = 'constance.apps.ConstanceConfig'
|
||||
|
||||
|
|
|
|||
|
|
@ -3,30 +3,21 @@ from decimal import Decimal
|
|||
import hashlib
|
||||
from operator import itemgetter
|
||||
|
||||
from django import forms
|
||||
from django import forms, VERSION
|
||||
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.shortcuts import render_to_response
|
||||
from django.template.context import RequestContext
|
||||
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.translation import ugettext_lazy as _
|
||||
import django
|
||||
|
||||
try:
|
||||
from django.utils.encoding import smart_bytes
|
||||
except ImportError:
|
||||
from django.utils.encoding import smart_str as smart_bytes
|
||||
|
||||
try:
|
||||
from django.conf.urls import patterns, url
|
||||
except ImportError: # Django < 1.4
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
|
||||
from . import LazyConfig, settings
|
||||
|
||||
|
|
@ -111,17 +102,18 @@ class ConstanceForm(forms.Form):
|
|||
|
||||
|
||||
class ConstanceAdmin(admin.ModelAdmin):
|
||||
change_list_template = 'admin/constance/change_list.html'
|
||||
|
||||
def get_urls(self):
|
||||
info = self.model._meta.app_label, self.model._meta.module_name
|
||||
return patterns('',
|
||||
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),
|
||||
)
|
||||
]
|
||||
|
||||
@csrf_protect_m
|
||||
def changelist_view(self, request, extra_context=None):
|
||||
|
|
@ -146,7 +138,7 @@ class ConstanceAdmin(admin.ModelAdmin):
|
|||
)
|
||||
return HttpResponseRedirect('.')
|
||||
context = {
|
||||
'config': [],
|
||||
'config_values': [],
|
||||
'title': _('Constance config'),
|
||||
'app_label': 'constance',
|
||||
'opts': Config._meta,
|
||||
|
|
@ -160,7 +152,7 @@ class ConstanceAdmin(admin.ModelAdmin):
|
|||
# Then if the returned value is None, get the default
|
||||
if value is None:
|
||||
value = getattr(config, name)
|
||||
context['config'].append({
|
||||
context['config_values'].append({
|
||||
'name': name,
|
||||
'default': localize(default),
|
||||
'help_text': _(help_text),
|
||||
|
|
@ -168,11 +160,12 @@ class ConstanceAdmin(admin.ModelAdmin):
|
|||
'modified': value != default,
|
||||
'form_field': form[name],
|
||||
})
|
||||
context['config'].sort(key=itemgetter('name'))
|
||||
context_instance = RequestContext(request,
|
||||
current_app=self.admin_site.name)
|
||||
return render_to_response('admin/constance/change_list.html',
|
||||
context, context_instance=context_instance)
|
||||
context['config_values'].sort(key=itemgetter('name'))
|
||||
request.current_app = self.admin_site.name
|
||||
# compatibility to be removed when 1.7 is deprecated
|
||||
extra = {'current_app': self.admin_site.name} if VERSION < (1, 8) else {}
|
||||
return TemplateResponse(request, self.change_list_template, context,
|
||||
**extra)
|
||||
|
||||
def has_add_permission(self, *args, **kwargs):
|
||||
return False
|
||||
|
|
@ -192,10 +185,12 @@ class Config(object):
|
|||
object_name = 'Config'
|
||||
model_name = module_name = 'config'
|
||||
verbose_name_plural = _('config')
|
||||
get_ordered_objects = lambda x: False
|
||||
abstract = False
|
||||
swapped = False
|
||||
|
||||
def get_ordered_objects(self):
|
||||
return False
|
||||
|
||||
def get_change_permission(self):
|
||||
return 'change_%s' % self.model_name
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from django.db.models import signals
|
||||
from django import VERSION
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
|
@ -5,3 +7,28 @@ from django.utils.translation import ugettext_lazy as _
|
|||
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, *args, **kwargs):
|
||||
"""
|
||||
Creates a fake content type and permission
|
||||
to be able to check for permissions
|
||||
"""
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
if ContentType._meta.installed and Permission._meta.installed:
|
||||
extra = {} if VERSION >= (1, 8) else {'name': 'config'}
|
||||
content_type, created = ContentType.objects.get_or_create(
|
||||
app_label='constance',
|
||||
model='config',
|
||||
**extra)
|
||||
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
name='Can change config',
|
||||
content_type=content_type,
|
||||
codename='change_config')
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
from django.core.cache import caches
|
||||
from django.core.cache.backends.locmem import LocMemCache
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.models.signals import post_save
|
||||
from django.core.cache import get_cache
|
||||
|
||||
try:
|
||||
from django.core.cache.backends.locmem import LocMemCache
|
||||
except ImportError:
|
||||
from django.core.cache.backends.locmem import CacheClass as LocMemCache
|
||||
|
||||
from .. import Backend
|
||||
from ... import settings
|
||||
|
|
@ -25,7 +21,7 @@ class DatabaseBackend(Backend):
|
|||
"correctly. Make sure it's in your INSTALLED_APPS setting.")
|
||||
|
||||
if settings.DATABASE_CACHE_BACKEND:
|
||||
self._cache = get_cache(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 "
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -3,14 +3,15 @@
|
|||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Yifu Yu <root@jackyyf.com>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django-constance\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-11-27 19:05+0100\n"
|
||||
"PO-Revision-Date: 2014-11-27 18:13+0000\n"
|
||||
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n"
|
||||
"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/django-constance/language/zh_CN/)\n"
|
||||
"PO-Revision-Date: 2015-03-15 18:40+0000\n"
|
||||
"Last-Translator: Yifu Yu <root@jackyyf.com>\n"
|
||||
"Language-Team: Chinese (China) (http://www.transifex.com/jezdez/django-constance/language/zh_CN/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
|
@ -22,13 +23,13 @@ msgstr ""
|
|||
msgid ""
|
||||
"Constance doesn't support config values of the type %(config_type)s. Please "
|
||||
"fix the value of '%(name)s'."
|
||||
msgstr ""
|
||||
msgstr "Constance不支持保存类型为%(config_type)s的值,请修正%(name)s的值。"
|
||||
|
||||
#: admin.py:91
|
||||
msgid ""
|
||||
"The settings have been modified by someone else. Please reload the form and "
|
||||
"resubmit your changes."
|
||||
msgstr ""
|
||||
msgstr "设置已经被他人修改过,请刷新页面并重新提交您的更改。"
|
||||
|
||||
#: admin.py:129
|
||||
msgid "Live settings updated successfully."
|
||||
|
|
@ -36,7 +37,7 @@ msgstr "成功更新实时配置"
|
|||
|
||||
#: admin.py:134
|
||||
msgid "Constance config"
|
||||
msgstr "常量配置"
|
||||
msgstr "Constance 配置页面"
|
||||
|
||||
#: admin.py:177
|
||||
msgid "config"
|
||||
|
|
@ -44,15 +45,15 @@ msgstr "配置"
|
|||
|
||||
#: apps.py:9
|
||||
msgid "Constance"
|
||||
msgstr ""
|
||||
msgstr "Constance模块"
|
||||
|
||||
#: backends/database/models.py:19
|
||||
msgid "constance"
|
||||
msgstr "常量"
|
||||
msgstr "Constance模块"
|
||||
|
||||
#: backends/database/models.py:20
|
||||
msgid "constances"
|
||||
msgstr "常量"
|
||||
msgstr "Constance模块"
|
||||
|
||||
#: templates/admin/constance/change_list.html:50
|
||||
msgid "Name"
|
||||
|
|
@ -68,7 +69,7 @@ msgstr "值"
|
|||
|
||||
#: templates/admin/constance/change_list.html:53
|
||||
msgid "Is modified"
|
||||
msgstr "是否修改"
|
||||
msgstr "是否修改过"
|
||||
|
||||
#: templates/admin/constance/change_list.html:79
|
||||
msgid "Save"
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
from django.db.models import signals
|
||||
|
||||
|
||||
def create_perm(app, created_models, verbosity, db, **kwargs):
|
||||
"""
|
||||
Creates a fake content type and permission
|
||||
to be able to check for permissions
|
||||
"""
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
if ContentType._meta.installed and Permission._meta.installed:
|
||||
content_type, created = ContentType.objects.get_or_create(
|
||||
name='config',
|
||||
app_label='constance',
|
||||
model='config')
|
||||
|
||||
permission, created = Permission.objects.get_or_create(
|
||||
name='Can change config',
|
||||
content_type=content_type,
|
||||
codename='change_config')
|
||||
|
||||
|
||||
signals.post_syncdb.connect(create_perm, dispatch_uid="constance.create_perm")
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
{% extends "admin/base_site.html" %}
|
||||
{% load admin_static admin_list i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
|
||||
{% block extrastyle %}
|
||||
|
|
@ -61,10 +60,10 @@
|
|||
<th><div class="text">{% trans "Is modified" %}</div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for item in config %}
|
||||
{% for item in config_values %}
|
||||
<tr class="{% cycle 'row1' 'row2' %}">
|
||||
<th>{{ item.name }}
|
||||
<div class="help">{{ item.help_text }}</div>
|
||||
<div class="help">{{ item.help_text|linebreaksbr }}</div>
|
||||
</th>
|
||||
<td>
|
||||
{{ item.default }}
|
||||
|
|
|
|||
1
constance/test/__init__.py
Normal file
1
constance/test/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .utils import override_config
|
||||
85
constance/test/utils.py
Normal file
85
constance/test/utils.py
Normal file
|
|
@ -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.keys():
|
||||
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)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.importlib import import_module
|
||||
from importlib import import_module
|
||||
|
||||
|
||||
def import_module_attr(path):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,33 @@
|
|||
Changelog
|
||||
---------
|
||||
|
||||
v1.1.1 (2015/10/01)
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fixed a regression in the 1.1 release that prevented the rendering of the
|
||||
admin view with constance values when using the context processor at the
|
||||
same time.
|
||||
|
||||
v1.1 (2015/09/24)
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** Dropped support for Python 2.6
|
||||
The supported versions are 2.7, 3.3 (on Django < 1.9) and 3.4.
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** Dropped support for Django 1.4, 1.5 and 1.6
|
||||
The supported versions are 1.7, 1.8 and the upcoming 1.9 release
|
||||
|
||||
* Added compatibility to Django 1.8 and 1.9.
|
||||
|
||||
* Added Spanish and Chinese (``zh_CN``) translations.
|
||||
|
||||
* Added :class:`override_config` decorator/context manager for easy
|
||||
:doc:`testing <testing>`.
|
||||
|
||||
* Added the ability to use linebreaks in config value help texts.
|
||||
|
||||
* Various testing fixes.
|
||||
|
||||
v1.0.1 (2015/01/07)
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = u'django-constance'
|
||||
copyright = u'2014, Comoga and individual contributors'
|
||||
copyright = u'2015, Comoga and individual contributors'
|
||||
|
||||
# The short X.Y version.
|
||||
try:
|
||||
|
|
@ -101,7 +101,7 @@ pygments_style = 'sphinx'
|
|||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ More documentation
|
|||
:maxdepth: 2
|
||||
|
||||
backends
|
||||
testing
|
||||
changes
|
||||
|
||||
Indices and tables
|
||||
|
|
|
|||
40
docs/testing.rst
Normal file
40
docs/testing.rst
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
Testing
|
||||
=======
|
||||
|
||||
Testing how your app behaves with different config values is achieved with the
|
||||
:class:`override_config` class. This intentionally mirrors the use of Django's
|
||||
:class:`~django.test.override_setting`.
|
||||
|
||||
.. py:class:: override_config(**kwargs)
|
||||
|
||||
Replaces key-value pairs in the config.
|
||||
Use as decorator or context manager.
|
||||
|
||||
Usage
|
||||
~~~~~
|
||||
|
||||
It can be used as a decorator at the :class:`~django.test.TestCase` level, the
|
||||
method level and also as a
|
||||
`context manager <https://www.python.org/dev/peps/pep-0343/>`_.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from constance import config
|
||||
from constance.test import override_config
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
@override_config(YOUR_NAME="Arthur of Camelot")
|
||||
class ExampleTestCase(TestCase):
|
||||
|
||||
def test_what_is_your_name(self):
|
||||
self.assertEqual(config.YOUR_NAME, "Arthur of Camelot")
|
||||
|
||||
@override_config(YOUR_QUEST="To find the Holy Grail")
|
||||
def test_what_is_your_quest(self):
|
||||
self.assertEqual(config.YOUR_QUEST, "To find the Holy Grail")
|
||||
|
||||
def test_what_is_your_favourite_color(self):
|
||||
with override_config(YOUR_FAVOURITE_COLOR="Blue?"):
|
||||
self.assertEqual(config.YOUR_FAVOURITE_COLOR, "Blue?")
|
||||
|
|
@ -72,6 +72,22 @@ TEMPLATE_LOADERS = (
|
|||
# 'django.template.loaders.eggs.Loader',
|
||||
)
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ CONSTANCE_CONFIG = {
|
|||
'DATE_VALUE': (date(2010, 12, 24), 'Merry Chrismas'),
|
||||
'TIME_VALUE': (time(23, 59, 59), 'And happy New Year'),
|
||||
'CHOICE_VALUE': ('yes', 'select yes or no', 'yes_no_null_select'),
|
||||
'LINEBREAK_VALUE': ('Spam spam', 'eggs\neggs'),
|
||||
}
|
||||
|
||||
DEBUG = True
|
||||
|
|
@ -79,3 +80,32 @@ DEBUG = True
|
|||
STATIC_ROOT = './static/'
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'constance.context_processors.config',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.core.context_processors.debug',
|
||||
'django.core.context_processors.i18n',
|
||||
'django.core.context_processors.media',
|
||||
'django.core.context_processors.static',
|
||||
'django.core.context_processors.tz',
|
||||
'django.core.context_processors.request',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'constance.context_processors.config',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib.auth.models import User, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.test import TestCase, RequestFactory
|
||||
from django.utils import six
|
||||
|
||||
from constance.admin import settings, Config
|
||||
|
||||
|
|
@ -44,3 +46,15 @@ class TestAdmin(TestCase):
|
|||
|
||||
response = self.options.changelist_view(request, {})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_str(self):
|
||||
ct = ContentType.objects.get(app_label='constance', model='config')
|
||||
self.assertEqual(six.text_type(ct), 'config')
|
||||
|
||||
def test_linebreaks(self):
|
||||
self.client.login(username='admin', password='nimda')
|
||||
request = self.rf.get('/admin/constance/config/')
|
||||
request.user = self.superuser
|
||||
response = self.options.changelist_view(request, {})
|
||||
self.assertContains(response, 'LINEBREAK_VALUE')
|
||||
self.assertContains(response, 'eggs<br />eggs')
|
||||
|
|
|
|||
34
tests/test_test_utils.py
Normal file
34
tests/test_test_utils.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from constance import config
|
||||
from constance.test import override_config
|
||||
|
||||
|
||||
class OverrideConfigFunctionDecoratorTestCase(TestCase):
|
||||
"""Test that the override_config decorator works correctly.
|
||||
|
||||
Test usage of override_config on test method and as context manager.
|
||||
"""
|
||||
def test_default_value_is_true(self):
|
||||
"""Assert that the default value of config.BOOL_VALUE is True."""
|
||||
self.assertTrue(config.BOOL_VALUE)
|
||||
|
||||
@override_config(BOOL_VALUE=False)
|
||||
def test_override_config_on_method_changes_config_value(self):
|
||||
"""Assert that the method decorator changes config.BOOL_VALUE."""
|
||||
self.assertFalse(config.BOOL_VALUE)
|
||||
|
||||
def test_override_config_as_context_manager_changes_config_value(self):
|
||||
"""Assert that the context manager changes config.BOOL_VALUE."""
|
||||
with override_config(BOOL_VALUE=False):
|
||||
self.assertFalse(config.BOOL_VALUE)
|
||||
|
||||
self.assertTrue(config.BOOL_VALUE)
|
||||
|
||||
|
||||
@override_config(BOOL_VALUE=False)
|
||||
class OverrideConfigClassDecoratorTestCase(TestCase):
|
||||
"""Test that the override_config decorator works on classes."""
|
||||
def test_override_config_on_class_changes_config_value(self):
|
||||
"""Asser that the class decorator changes config.BOOL_VALUE."""
|
||||
self.assertFalse(config.BOOL_VALUE)
|
||||
|
|
@ -1,11 +1,8 @@
|
|||
from django.contrib import admin
|
||||
|
||||
try:
|
||||
from django.conf.urls import patterns, include
|
||||
except ImportError:
|
||||
from django.conf.urls.defaults import patterns, include
|
||||
from django.conf.urls import url, include
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
urlpatterns = [
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
]
|
||||
|
|
|
|||
22
tox.ini
22
tox.ini
|
|
@ -1,30 +1,26 @@
|
|||
[tox]
|
||||
envlist =
|
||||
py26-django-14,
|
||||
py27-django-14,
|
||||
{py26,py27,py32,py33,py34,pypy}-django-{15,16},
|
||||
{py27,py32,py33,py34,pypy}-django-{17,master}
|
||||
{py27,py33,py34,pypy}-django-{17,18},
|
||||
{py27,py34,pypy}-django-master
|
||||
|
||||
[testenv]
|
||||
basepython =
|
||||
py26: python2.6
|
||||
py27: python2.7
|
||||
py32: python3.2
|
||||
py33: python3.3
|
||||
py34: python3.4
|
||||
py35: python3.5
|
||||
pypy: pypy
|
||||
deps =
|
||||
redis
|
||||
coverage
|
||||
django-picklefield
|
||||
py26: unittest2
|
||||
django-{14,15}: django-discover-runner
|
||||
django-14: Django>=1.4,<1.5
|
||||
django-15: Django>=1.5,<1.6
|
||||
django-16: Django>=1.6,<1.7
|
||||
django-17: Django>=1.7,<1.8
|
||||
django-master: https://github.com/django/django/archive/master.zip
|
||||
django-18: Django>=1.8,<1.9
|
||||
django-master: https://github.com/django/django/archive/master.tar.gz
|
||||
usedevelop = true
|
||||
commands =
|
||||
coverage run {envbindir}/django-admin.py test --settings=tests.settings -v2
|
||||
coverage run {envbindir}/django-admin.py test -v2
|
||||
coverage report
|
||||
setenv =
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
DJANGO_SETTINGS_MODULE=tests.settings
|
||||
|
|
|
|||
Loading…
Reference in a new issue