123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- from django import forms
- from django.utils.translation import gettext as _
- from django.utils.translation import ngettext
- from misago.admin.forms import YesNoSwitch
- __all__ = ["ChangeSettingsForm"]
- class ValidateChoicesNum(object):
- def __init__(self, min_choices=0, max_choices=0):
- self.min_choices = min_choices
- self.max_choices = max_choices
- def __call__(self, data):
- data_len = len(data)
- if self.min_choices and self.min_choices > data_len:
- message = ngettext(
- "You have to select at least %(choices)d option.",
- "You have to select at least %(choices)d options.",
- self.min_choices,
- )
- raise forms.ValidationError(message % {"choices": self.min_choices})
- if self.max_choices and self.max_choices < data_len:
- message = ngettext(
- "You cannot select more than %(choices)d option.",
- "You cannot select more than %(choices)d options.",
- self.max_choices,
- )
- raise forms.ValidationError(message % {"choices": self.max_choices})
- return data
- def basic_kwargs(setting, extra):
- kwargs = {
- "label": _(setting.name),
- "initial": setting.value,
- "required": extra.get("min_length") or extra.get("min"),
- }
- if setting.description:
- kwargs["help_text"] = _(setting.description)
- if setting.form_field == "yesno":
- # YesNoSwitch is int-base and setting is bool based
- # this means we need to do quick conversion
- kwargs["initial"] = 1 if kwargs["initial"] else 0
- if kwargs["required"]:
- if kwargs.get("help_text"):
- format = {"help_text": kwargs["help_text"]}
- kwargs["help_text"] = _("Required. %(help_text)s") % format
- else:
- kwargs["help_text"] = _("This field is required.")
- return kwargs
- def localise_choices(extra):
- return [(v, _(l)) for v, l in extra.get("choices", [])]
- def create_checkbox(setting, kwargs, extra):
- kwargs["widget"] = forms.CheckboxSelectMultiple()
- kwargs["choices"] = localise_choices(extra)
- if extra.get("min") or extra.get("max"):
- kwargs["validators"] = [
- ValidateChoicesNum(extra.pop("min", 0), extra.pop("max", 0))
- ]
- if setting.python_type == "int":
- return forms.TypedMultipleChoiceField(coerce="int", **kwargs)
- else:
- return forms.MultipleChoiceField(**kwargs)
- def create_choice(setting, kwargs, extra):
- if setting.form_field == "choice":
- kwargs["widget"] = forms.RadioSelect()
- else:
- kwargs["widget"] = forms.Select()
- kwargs["choices"] = localise_choices(extra)
- if setting.python_type == "int":
- return forms.TypedChoiceField(coerce="int", **kwargs)
- else:
- return forms.ChoiceField(**kwargs)
- def create_text(setting, kwargs, extra):
- kwargs.update(extra)
- if setting.python_type == "int":
- return forms.IntegerField(**kwargs)
- else:
- return forms.CharField(**kwargs)
- def create_textarea(setting, kwargs, extra):
- widget_kwargs = {}
- if extra.get("min_length", 0) == 0:
- kwargs["required"] = False
- if extra.get("rows", 0):
- widget_kwargs["attrs"] = {"rows": extra.pop("rows")}
- kwargs["widget"] = forms.Textarea(**widget_kwargs)
- return forms.CharField(**kwargs)
- def create_yesno(setting, kwargs, extra):
- return YesNoSwitch(**kwargs)
- FIELD_STYPES = {
- "checkbox": create_checkbox,
- "radio": create_choice,
- "select": create_choice,
- "text": create_text,
- "textarea": create_textarea,
- "yesno": create_yesno,
- }
- def setting_field(FormType, setting):
- field_factory = FIELD_STYPES[setting.form_field]
- field_extra = setting.field_extra
- form_field = field_factory(setting, basic_kwargs(setting, field_extra), field_extra)
- FormType = type(
- "FormType%s" % setting.pk, (FormType,), {setting.setting: form_field}
- )
- return FormType
- def ChangeSettingsForm(data=None, group=None):
- """factory method that builds valid form for settings group"""
- class FormType(forms.Form):
- pass
- fieldsets = []
- fieldset_legend = None
- fieldset_form = FormType
- fieldset_fields = False
- for setting in group.setting_set.order_by("order"):
- if setting.legend and setting.legend != fieldset_legend:
- if fieldset_fields:
- fieldsets.append(
- {"legend": fieldset_legend, "form": fieldset_form(data)}
- )
- fieldset_legend = setting.legend
- fieldset_form = FormType
- fieldset_fields = False
- fieldset_fields = True
- fieldset_form = setting_field(fieldset_form, setting)
- if fieldset_fields:
- fieldsets.append({"legend": fieldset_legend, "form": fieldset_form(data)})
- return fieldsets
|