forms.py 4.9 KB

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