Improvements settings admin management
This commit is contained in:
parent
759c01c64c
commit
929d9beb5c
12
TODO.md
12
TODO.md
|
@ -294,15 +294,3 @@ https://code.djangoproject.com/ticket/24576
|
||||||
# TODO orchestra related services code reload: celery/uwsgi reloading find aonther way without root and implement reload
|
# TODO orchestra related services code reload: celery/uwsgi reloading find aonther way without root and implement reload
|
||||||
# insert settings on dashboard dynamically
|
# insert settings on dashboard dynamically
|
||||||
|
|
||||||
# rename "edit settings" -> change settings
|
|
||||||
|
|
||||||
# View settings file
|
|
||||||
contrib/orders/models.py: if type(instance) in services:
|
|
||||||
contrib/orders/models.py: if type(instance) in services:
|
|
||||||
contrib/orders/helpers.py: if type(node) in services:
|
|
||||||
contrib/bills/admin.py: return [inline for inline in inlines if type(inline) is not BillLineInline]
|
|
||||||
contrib/bills/admin.py: return [inline for inline in inlines if type(inline) is not ClosedBillLineInline]
|
|
||||||
contrib/accounts/actions.py.save: if type(service) in registered_services:
|
|
||||||
contrib/accounts/actions.py: if type(service) in registered_services:
|
|
||||||
permissions/options.py: for func in inspect.getmembers(type(self), predicate=inspect.ismethod):
|
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ def get_accounts():
|
||||||
def get_administration_items():
|
def get_administration_items():
|
||||||
childrens = []
|
childrens = []
|
||||||
if isinstalled('orchestra.contrib.settings'):
|
if isinstalled('orchestra.contrib.settings'):
|
||||||
url = reverse('admin:settings_edit_settings')
|
url = reverse('admin:settings_setting_change')
|
||||||
childrens.append(items.MenuItem(_("Settings"), url))
|
childrens.append(items.MenuItem(_("Settings"), url))
|
||||||
if isinstalled('orchestra.contrib.services'):
|
if isinstalled('orchestra.contrib.services'):
|
||||||
url = reverse('admin:services_service_changelist')
|
url = reverse('admin:services_service_changelist')
|
||||||
|
|
|
@ -259,8 +259,8 @@ class BillAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||||
def get_inline_instances(self, request, obj=None):
|
def get_inline_instances(self, request, obj=None):
|
||||||
inlines = super(BillAdmin, self).get_inline_instances(request, obj)
|
inlines = super(BillAdmin, self).get_inline_instances(request, obj)
|
||||||
if obj and not obj.is_open:
|
if obj and not obj.is_open:
|
||||||
return [inline for inline in inlines if type(inline) is not BillLineInline]
|
return [inline for inline in inlines if not isinstance(inline, BillLineInline)]
|
||||||
return [inline for inline in inlines if type(inline) is not ClosedBillLineInline]
|
return [inline for inline in inlines if not isinstance(inline, ClosedBillLineInline)]
|
||||||
|
|
||||||
def formfield_for_dbfield(self, db_field, **kwargs):
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
""" Make value input widget bigger """
|
""" Make value input widget bigger """
|
||||||
|
|
|
@ -87,10 +87,10 @@ DOMAINS_DEFAULT_NS = Setting('DOMAINS_DEFAULT_NS', (
|
||||||
|
|
||||||
DOMAINS_FORBIDDEN = Setting('DOMAINS_FORBIDDEN', '',
|
DOMAINS_FORBIDDEN = Setting('DOMAINS_FORBIDDEN', '',
|
||||||
help_text=(
|
help_text=(
|
||||||
"This setting prevents users from providing random domain names, i.e. google.com"
|
"This setting prevents users from providing random domain names, i.e. google.com<br>"
|
||||||
"You can generate a 5K forbidden domains list from Alexa's top 1M"
|
"You can generate a 5K forbidden domains list from Alexa's top 1M:<br>"
|
||||||
"wget http://s3.amazonaws.com/alexa-static/top-1m.csv.zip -O /tmp/top-1m.csv.zip"
|
"<tt> wget http://s3.amazonaws.com/alexa-static/top-1m.csv.zip -O /tmp/top-1m.csv.zip && "
|
||||||
"unzip -p /tmp/top-1m.csv.zip | head -n 5000 | sed 's/^.*,//' > forbidden_domains.list"
|
"unzip -p /tmp/top-1m.csv.zip | head -n 5000 | sed 's/^.*,//' > forbidden_domains.list</tt><br>"
|
||||||
"'%(site_dir)s/forbidden_domains.list')"
|
"'%(site_dir)s/forbidden_domains.list')"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,7 +14,7 @@ SAAS_ENABLED_SERVICES = Setting('SAAS_ENABLED_SERVICES', (
|
||||||
'orchestra.contrib.saas.services.seafile.SeaFileService',
|
'orchestra.contrib.saas.services.seafile.SeaFileService',
|
||||||
),
|
),
|
||||||
# lazy loading
|
# lazy loading
|
||||||
choices=lambda : ((s.get_class_path(), s.get_class_path()) for s in saas.services.SoftwareService.get_plugins()),
|
choices=lambda: ((s.get_class_path(), s.get_class_path()) for s in saas.services.SoftwareService.get_plugins()),
|
||||||
multiple=True,
|
multiple=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ SAAS_WORDPRESS_ADMIN_PASSWORD = Setting('SAAS_WORDPRESSMU_ADMIN_PASSWORD',
|
||||||
|
|
||||||
|
|
||||||
SAAS_WORDPRESS_BASE_URL = Setting('SAAS_WORDPRESS_BASE_URL',
|
SAAS_WORDPRESS_BASE_URL = Setting('SAAS_WORDPRESS_BASE_URL',
|
||||||
'http://blogs.{}/'.format(ORCHESTRA_BASE_DOMAIN)
|
'https://blogs.{}/'.format(ORCHESTRA_BASE_DOMAIN)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ from functools import partial
|
||||||
from django.contrib import admin, messages
|
from django.contrib import admin, messages
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from django.views.generic.edit import FormView
|
from django.views import generic
|
||||||
from django.utils.translation import ngettext, ugettext_lazy as _
|
from django.utils.translation import ngettext, ugettext_lazy as _
|
||||||
|
|
||||||
from orchestra.settings import Setting
|
from orchestra.settings import Setting
|
||||||
|
@ -13,7 +13,7 @@ from . import parser
|
||||||
from .forms import SettingFormSet
|
from .forms import SettingFormSet
|
||||||
|
|
||||||
|
|
||||||
class SettingView(FormView):
|
class SettingView(generic.edit.FormView):
|
||||||
template_name = 'admin/settings/change_form.html'
|
template_name = 'admin/settings/change_form.html'
|
||||||
form_class = SettingFormSet
|
form_class = SettingFormSet
|
||||||
success_url = '.'
|
success_url = '.'
|
||||||
|
@ -38,10 +38,8 @@ class SettingView(FormView):
|
||||||
'default': setting.default,
|
'default': setting.default,
|
||||||
'type': type(setting.default),
|
'type': type(setting.default),
|
||||||
'value': setting.value,
|
'value': setting.value,
|
||||||
'choices': setting.choices,
|
'setting': setting,
|
||||||
'app': app,
|
'app': app,
|
||||||
'editable': setting.editable,
|
|
||||||
'multiple': setting.multiple,
|
|
||||||
}
|
}
|
||||||
if app == 'ORCHESTRA':
|
if app == 'ORCHESTRA':
|
||||||
initial_data.insert(account, initial)
|
initial_data.insert(account, initial)
|
||||||
|
@ -79,11 +77,28 @@ class SettingView(FormView):
|
||||||
_("%s changes successfully applied, the orchestra is going to be restarted...") % n,
|
_("%s changes successfully applied, the orchestra is going to be restarted...") % n,
|
||||||
n)
|
n)
|
||||||
)
|
)
|
||||||
# TODO find aonther way without root and implement reload
|
sys.run('{ sleep 2 && touch %s/wsgi.py; } &' % paths.get_project_dir(), async=True)
|
||||||
# sys.run('echo { sleep 2 && python3 %s/manage.py reload; } &' % paths.get_site_dir(), async=True)
|
|
||||||
else:
|
else:
|
||||||
messages.success(self.request, _("No changes have been detected."))
|
messages.success(self.request, _("No changes have been detected."))
|
||||||
return super(SettingView, self).form_valid(form)
|
return super(SettingView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
admin.site.register_url(r'^settings/setting/$', SettingView.as_view(), 'settings_edit_settings')
|
class SettingFileView(generic.TemplateView):
|
||||||
|
template_name = 'admin/settings/view.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(SettingFileView, self).get_context_data(**kwargs)
|
||||||
|
settings_file = parser.get_settings_file()
|
||||||
|
with open(settings_file, 'r') as handler:
|
||||||
|
content = handler.read()
|
||||||
|
context.update({
|
||||||
|
'title': _("Settings file content"),
|
||||||
|
'settings_file': settings_file,
|
||||||
|
'content': content,
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register_url(r'^settings/setting/view/$', SettingFileView.as_view(), 'settings_setting_view')
|
||||||
|
admin.site.register_url(r'^settings/setting/$', SettingView.as_view(), 'settings_setting_change')
|
||||||
|
|
||||||
|
|
|
@ -48,14 +48,16 @@ class SettingForm(ReadOnlyFormMixin, forms.Form):
|
||||||
initial = kwargs.get('initial')
|
initial = kwargs.get('initial')
|
||||||
if initial:
|
if initial:
|
||||||
self.setting_type = initial['type']
|
self.setting_type = initial['type']
|
||||||
|
self.setting = initial['setting']
|
||||||
|
setting = self.setting
|
||||||
serialized_value = parser.serialize(initial['value'])
|
serialized_value = parser.serialize(initial['value'])
|
||||||
serialized_default = parser.serialize(initial['default'])
|
serialized_default = parser.serialize(initial['default'])
|
||||||
if not initial['editable'] or isinstance(serialized_value, parser.NotSupported):
|
if not setting.editable or isinstance(serialized_value, parser.NotSupported):
|
||||||
field = self.NON_EDITABLE
|
field = self.NON_EDITABLE
|
||||||
else:
|
else:
|
||||||
choices = initial.get('choices')
|
choices = setting.choices
|
||||||
field = forms.ChoiceField
|
field = forms.ChoiceField
|
||||||
multiple = initial['multiple']
|
multiple = setting.multiple
|
||||||
if multiple:
|
if multiple:
|
||||||
field = partial(forms.MultipleChoiceField, widget=forms.CheckboxSelectMultiple)
|
field = partial(forms.MultipleChoiceField, widget=forms.CheckboxSelectMultiple)
|
||||||
if choices:
|
if choices:
|
||||||
|
@ -68,26 +70,25 @@ class SettingForm(ReadOnlyFormMixin, forms.Form):
|
||||||
else:
|
else:
|
||||||
field = self.FORMFIELD_FOR_SETTING_TYPE.get(self.setting_type, self.NON_EDITABLE)
|
field = self.FORMFIELD_FOR_SETTING_TYPE.get(self.setting_type, self.NON_EDITABLE)
|
||||||
field = deepcopy(field)
|
field = deepcopy(field)
|
||||||
value = initial['value']
|
|
||||||
default = initial['default']
|
|
||||||
real_field = field
|
real_field = field
|
||||||
while isinstance(real_field, partial):
|
while isinstance(real_field, partial):
|
||||||
real_field = real_field.func
|
real_field = real_field.func
|
||||||
# Do not serialize following form types
|
# Do not serialize following form types
|
||||||
|
value = initial['value']
|
||||||
|
default = initial['default']
|
||||||
|
self.changed = bool(value != default)
|
||||||
if real_field not in (forms.MultipleChoiceField, forms.BooleanField):
|
if real_field not in (forms.MultipleChoiceField, forms.BooleanField):
|
||||||
value = serialized_value
|
value = serialized_value
|
||||||
if real_field is not forms.BooleanField:
|
|
||||||
default = serialized_default
|
default = serialized_default
|
||||||
initial['value'] = value
|
initial['value'] = value
|
||||||
initial['default'] = default
|
initial['default'] = default
|
||||||
super(SettingForm, self).__init__(*args, **kwargs)
|
super(SettingForm, self).__init__(*args, **kwargs)
|
||||||
if initial:
|
if initial:
|
||||||
self.changed = bool(value != default)
|
|
||||||
self.fields['value'] = field(label=_("value"))
|
self.fields['value'] = field(label=_("value"))
|
||||||
if isinstance(self.fields['value'].widget, forms.Textarea):
|
if isinstance(self.fields['value'].widget, forms.Textarea):
|
||||||
rows = math.ceil(len(value)/65)
|
rows = math.ceil(len(value)/65)
|
||||||
self.fields['value'].widget.attrs['rows'] = rows
|
self.fields['value'].widget.attrs['rows'] = rows
|
||||||
self.fields['name'].help_text = initial['help_text']
|
self.fields['name'].help_text = mark_safe(setting.help_text)
|
||||||
self.fields['name'].widget.attrs['readonly'] = True
|
self.fields['name'].widget.attrs['readonly'] = True
|
||||||
self.app = initial['app']
|
self.app = initial['app']
|
||||||
|
|
||||||
|
@ -101,11 +102,10 @@ class SettingForm(ReadOnlyFormMixin, forms.Form):
|
||||||
value = eval(value, parser.get_eval_context())
|
value = eval(value, parser.get_eval_context())
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise ValidationError(str(exc))
|
raise ValidationError(str(exc))
|
||||||
|
self.setting.validate_value(value)
|
||||||
if not isinstance(value, self.setting_type):
|
if not isinstance(value, self.setting_type):
|
||||||
if self.setting_type in (tuple, list) and isinstance(value, (tuple, list)):
|
if self.setting_type in (tuple, list) and isinstance(value, (tuple, list)):
|
||||||
value = self.setting_type(value)
|
value = self.setting_type(value)
|
||||||
else:
|
|
||||||
raise ValidationError("Please provide a %s." % self.setting_type.__name__)
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,15 @@
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<ul class="object-tools">
|
||||||
|
{% block object-tools-items %}
|
||||||
|
<li>
|
||||||
|
<a href="./view/" class="historylink">{% trans "View file" %}</a>
|
||||||
|
</li>
|
||||||
|
{% endblock %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<form method="post" action="">{% csrf_token %}
|
<form method="post" action="">{% csrf_token %}
|
||||||
{% if diff %}
|
{% if diff %}
|
||||||
|
@ -69,7 +76,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ field.errors.as_ul }}
|
{{ field.errors.as_ul }}
|
||||||
<div style="font-family:monospace">{{ field }}{% if forloop.last %}{% if form.changed %}<div style="float:right" title="Changed">†</div>{% endif %}{% endif %}</div>
|
<div style="font-family:monospace">{{ field }}{% if forloop.last %}{% if form.changed %}<div style="float:right" title="Changed">*</div>{% endif %}{% endif %}</div>
|
||||||
<p class="help" style="max-width:100px; white-space:nowrap;">{{ field.help_text }}</p>
|
<p class="help" style="max-width:100px; white-space:nowrap;">{{ field.help_text }}</p>
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -82,5 +89,3 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "admin/base_site.html" %}
|
||||||
|
{% load i18n l10n %}
|
||||||
|
{% load url from future %}
|
||||||
|
{% load admin_urls static utils %}
|
||||||
|
|
||||||
|
{% block extrastyle %}
|
||||||
|
{{ block.super }}
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static "orchestra/css/hide-inline-id.css" %}" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||||
|
› <a href="../">Settings</a>
|
||||||
|
› View file content
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
{% blocktrans %}
|
||||||
|
<p>Current <tt>{{ settings_file }}</tt> content.</p>
|
||||||
|
{% endblocktrans %}
|
||||||
|
<PRE>{{ content }}</PRE>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -11,14 +11,26 @@ from IPy import IP
|
||||||
from ..utils.python import import_class
|
from ..utils.python import import_class
|
||||||
|
|
||||||
|
|
||||||
def all_valid(kwargs):
|
def all_valid(*args):
|
||||||
""" helper function to merge multiple validators at once """
|
""" helper function to merge multiple validators at once """
|
||||||
|
if len(args) == 1:
|
||||||
|
# Dict
|
||||||
errors = {}
|
errors = {}
|
||||||
|
kwargs = args
|
||||||
for field, validator in kwargs.items():
|
for field, validator in kwargs.items():
|
||||||
try:
|
try:
|
||||||
validator[0](*validator[1:])
|
validator[0](*validator[1:])
|
||||||
except ValidationError as error:
|
except ValidationError as error:
|
||||||
errors[field] = error
|
errors[field] = error
|
||||||
|
else:
|
||||||
|
# List
|
||||||
|
errors = []
|
||||||
|
value, validators = args
|
||||||
|
for validator in validators:
|
||||||
|
try:
|
||||||
|
validator(value)
|
||||||
|
except ValidationError as error:
|
||||||
|
errors.append(error)
|
||||||
if errors:
|
if errors:
|
||||||
raise ValidationError(errors)
|
raise ValidationError(errors)
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,8 @@ class ReadOnlyFormMixin(object):
|
||||||
field.widget = SpanWidget()
|
field.widget = SpanWidget()
|
||||||
if hasattr(self, 'instance'):
|
if hasattr(self, 'instance'):
|
||||||
# Model form
|
# Model form
|
||||||
original_value = str(getattr(self.instance, name))
|
original_value = getattr(self.instance, name)
|
||||||
else:
|
else:
|
||||||
original_value = str(self.initial.get(name))
|
original_value = self.initial.get(name)
|
||||||
field.widget.original_value = original_value
|
field.widget.original_value = original_value
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ class SpanWidget(forms.Widget):
|
||||||
Renders a value wrapped in a <span> tag.
|
Renders a value wrapped in a <span> tag.
|
||||||
Requires use of specific form support. (see ReadonlyForm or ReadonlyModelForm)
|
Requires use of specific form support. (see ReadonlyForm or ReadonlyModelForm)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.tag = kwargs.pop('tag', '<span>')
|
self.tag = kwargs.pop('tag', '<span>')
|
||||||
super(SpanWidget, self).__init__(*args, **kwargs)
|
super(SpanWidget, self).__init__(*args, **kwargs)
|
||||||
|
@ -22,8 +21,8 @@ class SpanWidget(forms.Widget):
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
original_value = self.original_value
|
original_value = self.original_value
|
||||||
# Display icon
|
# Display icon
|
||||||
if original_value in ('True', 'False') or isinstance(original_value, bool):
|
if isinstance(original_value, bool):
|
||||||
icon = static('admin/img/icon-%s.gif' % 'yes' if original_value else 'no')
|
icon = static('admin/img/icon-%s.gif' % ('yes' if original_value else 'no',))
|
||||||
return mark_safe('<img src="%s" alt="%s">' % (icon, str(original_value)))
|
return mark_safe('<img src="%s" alt="%s">' % (icon, str(original_value)))
|
||||||
tag = self.tag[:-1]
|
tag = self.tag[:-1]
|
||||||
endtag = '/'.join((self.tag[0], self.tag[1:]))
|
endtag = '/'.join((self.tag[0], self.tag[1:]))
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from .core import validators
|
||||||
|
|
||||||
|
|
||||||
class Setting(object):
|
class Setting(object):
|
||||||
"""
|
"""
|
||||||
|
@ -20,11 +23,12 @@ class Setting(object):
|
||||||
value = ("'%s'" if isinstance(value, str) else '%s') % value
|
value = ("'%s'" if isinstance(value, str) else '%s') % value
|
||||||
return '<%s: %s>' % (self.name, value)
|
return '<%s: %s>' % (self.name, value)
|
||||||
|
|
||||||
def __new__(cls, name, default, help_text="", choices=None, editable=True, multiple=False, call_init=False):
|
def __new__(cls, name, default, help_text="", choices=None, editable=True, multiple=False,
|
||||||
|
validators=[], types=[], call_init=False):
|
||||||
if call_init:
|
if call_init:
|
||||||
return super(Setting, cls).__new__(cls)
|
return super(Setting, cls).__new__(cls)
|
||||||
cls.settings[name] = cls(name, default, help_text=help_text, choices=choices,
|
cls.settings[name] = cls(name, default, help_text=help_text, choices=choices,
|
||||||
editable=editable, multiple=multiple, call_init=True)
|
editable=editable, multiple=multiple, validators=validators, types=types, call_init=True)
|
||||||
return cls.get_value(name, default)
|
return cls.get_value(name, default)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -32,22 +36,31 @@ class Setting(object):
|
||||||
for name, value in kwargs.items():
|
for name, value in kwargs.items():
|
||||||
setattr(self, name, value)
|
setattr(self, name, value)
|
||||||
self.value = self.get_value(self.name, self.default)
|
self.value = self.get_value(self.name, self.default)
|
||||||
|
self.validate_value(self.value)
|
||||||
self.settings[name] = self
|
self.settings[name] = self
|
||||||
|
|
||||||
|
def validate_value(self, value):
|
||||||
|
validators.all_valid(value, self.validators)
|
||||||
|
valid_types = list(self.types)
|
||||||
|
if isinstance(self.default, (list, tuple)):
|
||||||
|
valid_types.extend([list, tuple])
|
||||||
|
valid_types.append(type(self.default))
|
||||||
|
if not isinstance(value, tuple(valid_types)):
|
||||||
|
raise ValidationError("%s is not a valid type (%s)." %
|
||||||
|
(type(value).__name__, ', '.join(t.__name__ for t in valid_types))
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_value(cls, name, default):
|
def get_value(cls, name, default):
|
||||||
return getattr(cls.conf_settings, name, default)
|
return getattr(cls.conf_settings, name, default)
|
||||||
|
|
||||||
|
|
||||||
# TODO validation, defaults to same type
|
|
||||||
|
|
||||||
|
|
||||||
ORCHESTRA_BASE_DOMAIN = Setting('ORCHESTRA_BASE_DOMAIN',
|
ORCHESTRA_BASE_DOMAIN = Setting('ORCHESTRA_BASE_DOMAIN',
|
||||||
'orchestra.lan'
|
'orchestra.lan'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
ORCHESTRA_SITE_URL = Setting('ORCHESTRA_SITE_URL', 'http://orchestra.%s' % ORCHESTRA_BASE_DOMAIN,
|
ORCHESTRA_SITE_URL = Setting('ORCHESTRA_SITE_URL', 'https://orchestra.%s' % ORCHESTRA_BASE_DOMAIN,
|
||||||
help_text=_("Domain name used when it will not be possible to infere the domain from a request."
|
help_text=_("Domain name used when it will not be possible to infere the domain from a request."
|
||||||
"For example in periodic tasks.")
|
"For example in periodic tasks.")
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue