123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- from __future__ import unicode_literals
- from future.builtins import int
- from collections import defaultdict
- from django import forms
- from django.utils.safestring import mark_safe
- from django.utils.translation import activate, get_language, ugettext_lazy as _
- from django.template.defaultfilters import urlize
- from mezzanine.conf import settings, registry
- from mezzanine.conf.models import Setting
- if settings.USE_MODELTRANSLATION:
- from collections import OrderedDict
- from modeltranslation.utils import build_localized_fieldname
- FIELD_TYPES = {
- bool: forms.BooleanField,
- int: forms.IntegerField,
- float: forms.FloatField,
- }
- class SettingsForm(forms.Form):
- """
- Form for settings - creates a field for each setting in
- ``mezzanine.conf`` that is marked as editable.
- """
- def __init__(self, *args, **kwargs):
- super(SettingsForm, self).__init__(*args, **kwargs)
- # Create a form field for each editable setting's from its type.
- active_language = get_language()
- for name in sorted(registry.keys()):
- setting = registry[name]
- if setting["editable"]:
- field_class = FIELD_TYPES.get(setting["type"], forms.CharField)
- if settings.USE_MODELTRANSLATION and setting["translatable"]:
- for code in OrderedDict(settings.LANGUAGES):
- try:
- activate(code)
- except:
- pass
- else:
- self._init_field(setting, field_class, name, code)
- else:
- self._init_field(setting, field_class, name)
- activate(active_language)
- def _init_field(self, setting, field_class, name, code=None):
- """
- Initialize a field whether it is built with a custom name for a
- specific translation language or not.
- """
- kwargs = {
- "label": setting["label"] + ":",
- "required": setting["type"] in (int, float),
- "initial": getattr(settings, name),
- "help_text": self.format_help(setting["description"]),
- }
- if setting["choices"]:
- field_class = forms.ChoiceField
- kwargs["choices"] = setting["choices"]
- field_instance = field_class(**kwargs)
- code_name = ('_modeltranslation_' + code if code else '')
- self.fields[name + code_name] = field_instance
- css_class = field_class.__name__.lower()
- field_instance.widget.attrs["class"] = css_class
- if code:
- field_instance.widget.attrs["class"] += " modeltranslation"
- def __iter__(self):
- """
- Calculate and apply a group heading to each field and order by
- the heading.
- """
- fields = list(super(SettingsForm, self).__iter__())
- group = lambda field: field.name.split("_", 1)[0].title()
- misc = _("Miscellaneous")
- groups = defaultdict(int)
- for field in fields:
- groups[group(field)] += 1
- for (i, field) in enumerate(fields):
- setattr(fields[i], "group", group(field))
- if groups[fields[i].group] == 1:
- fields[i].group = misc
- return iter(sorted(fields, key=lambda x: (x.group == misc, x.group)))
- def save(self):
- """
- Save each of the settings to the DB.
- """
- active_language = get_language()
- for (name, value) in self.cleaned_data.items():
- if name not in registry:
- name, code = name.rsplit('_modeltranslation_', 1)
- else:
- code = None
- setting_obj, created = Setting.objects.get_or_create(name=name)
- if settings.USE_MODELTRANSLATION:
- if registry[name]["translatable"]:
- try:
- activate(code)
- except:
- pass
- finally:
- setting_obj.value = value
- activate(active_language)
- else:
- # Duplicate the value of the setting for every language
- for code in OrderedDict(settings.LANGUAGES):
- setattr(setting_obj,
- build_localized_fieldname('value', code),
- value)
- else:
- setting_obj.value = value
- setting_obj.save()
- def format_help(self, description):
- """
- Format the setting's description into HTML.
- """
- for bold in ("``", "*"):
- parts = []
- if description is None:
- description = ""
- for i, s in enumerate(description.split(bold)):
- parts.append(s if i % 2 == 0 else "<b>%s</b>" % s)
- description = "".join(parts)
- description = urlize(description, autoescape=False)
- return mark_safe(description.replace("\n", "<br>"))
|