forms.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. from django.utils.translation import ugettext_lazy as _, ungettext_lazy
  2. from misago.core import forms, timezones
  3. __ALL__ = ['ChangeSettingsForm']
  4. class ValidateChoicesNum(object):
  5. def __init__(self, min_choices=0, max_choices=0):
  6. self.min_choices = min_choices,
  7. self.max_choices = max_choices
  8. def __call__(self, data):
  9. data_len = len(data)
  10. if self.min_choices and self.min_choices > data_len:
  11. message = ungettext_lazy(
  12. 'You have to select at least one option.',
  13. 'You have to select at least %(min_choices)d options.',
  14. self.min_choices)
  15. message = message % {'min_choices': self.min_choices}
  16. raise forms.ValidationError(message)
  17. if self.max_choices and self.max_choices < data_len:
  18. message = ungettext_lazy(
  19. 'You cannot select more than one option.',
  20. 'You cannot select more than %(max_choices)d options.',
  21. self.max_choices)
  22. message = message % {'max_choices': self.max_choices}
  23. raise forms.ValidationError(message)
  24. return data
  25. def basic_kwargs(setting, extra):
  26. kwargs = {
  27. 'label': _(setting.name),
  28. 'initial': setting.value,
  29. 'required': extra.get('min_length') or extra.get('min'),
  30. }
  31. if setting.description:
  32. kwargs['help_text'] = _(setting.description)
  33. if kwargs['required']:
  34. if kwargs.get('help_text'):
  35. format = {'help_text': kwargs['help_text']}
  36. kwargs['help_text'] = _('Required. %(help_text)s') % format
  37. else:
  38. kwargs['help_text'] = _('This field is required.')
  39. return kwargs
  40. def create_checkbox(setting, kwargs, extra):
  41. kwargs['widget'] = forms.CheckboxSelectMultiple()
  42. kwargs['choices'] = extra.get('choices', [])
  43. if extra.get('min') or extra.get('max'):
  44. kwargs['validators'] = [ValidateChoicesNum(extra.get('min', 0),
  45. extra.get('max', 0))]
  46. if setting.python_type == 'int':
  47. return forms.TypedMultipleChoiceField(coerce='int', **kwargs)
  48. else:
  49. return forms.MultipleChoiceField(**kwargs)
  50. def create_choice(setting, kwargs, extra):
  51. if setting.form_field == 'choice':
  52. kwargs['widget'] = forms.RadioSelect()
  53. else:
  54. kwargs['widget'] = forms.Select()
  55. kwargs['choices'] = extra.get('choices', [])
  56. if kwargs['choices'] == '#TZ#':
  57. kwargs['choices'] = timezones.choices()
  58. if setting.python_type == 'int':
  59. return forms.TypedChoiceField(coerce='int', **kwargs)
  60. else:
  61. return forms.ChoiceField(**kwargs)
  62. def create_text(setting, kwargs, extra):
  63. kwargs.update(extra)
  64. if setting.python_type == 'int':
  65. return forms.IntegerField(**kwargs)
  66. else:
  67. return forms.CharField(**kwargs)
  68. def create_textarea(setting, kwargs, extra):
  69. widget_kwargs = {}
  70. if extra.get('min_length', 0) == 0:
  71. kwargs['required'] = False
  72. if extra.get('rows', 0):
  73. widget_kwargs['attrs'] = {'rows': extra.pop('rows')}
  74. kwargs['widget'] = forms.Textarea(**widget_kwargs)
  75. return forms.CharField(**kwargs)
  76. def create_yesno(setting, kwargs, extra):
  77. kwargs['widget'] = forms.RadioSelect()
  78. kwargs['choices'] = ((0, _('No')), (1, _('Yes')))
  79. return forms.TypedChoiceField(coerce='int', **kwargs)
  80. FIELD_STYPES = {
  81. 'checkbox': create_checkbox,
  82. 'radio': create_choice,
  83. 'select': create_choice,
  84. 'text': create_text,
  85. 'textarea': create_textarea,
  86. 'yesno': create_yesno,
  87. }
  88. def setting_field(FormType, setting):
  89. field_factory = FIELD_STYPES[setting.form_field]
  90. field_extra = setting.field_extra
  91. form_field = field_factory(setting,
  92. basic_kwargs(setting, field_extra),
  93. field_extra)
  94. if setting.legend:
  95. form_field.legend = _(setting.legend)
  96. FormType = type('FormType%s' % setting.pk, (FormType,),
  97. {setting.setting: form_field})
  98. return FormType
  99. def ChangeSettingsForm(data=None, group=None):
  100. """
  101. Factory method that builds valid form for settings group
  102. """
  103. class FormType(forms.Form):
  104. pass
  105. fieldsets = []
  106. fieldset_legend = None
  107. fieldset_form = FormType
  108. fieldset_fields = False
  109. for setting in group.setting_set.order_by('order'):
  110. if setting.legend and setting.legend != fieldset_legend:
  111. if fieldset_fields != False:
  112. fieldsets.append(
  113. {'legend': fieldset_legend, 'form': fieldset_form(data)})
  114. fieldset_legend = setting.legend
  115. fieldset_form = FormType
  116. fieldset_fields = False
  117. fieldset_fields = True
  118. fieldset_form = setting_field(fieldset_form, setting)
  119. if fieldset_fields:
  120. fieldsets.append(
  121. {'legend': fieldset_legend, 'form': fieldset_form(data)})
  122. return fieldsets