123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- from django import forms
- from django.utils.translation import ugettext as _
- from django.utils.translation import ungettext
- from misago.core.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 = ungettext(
- '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 = ungettext(
- '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
|