forms.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.utils.forms
  4. ~~~~~~~~~~~~~~~~~~~
  5. This module contains stuff for forms.
  6. :copyright: (c) 2017 by the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. from wtforms import (TextField, IntegerField, FloatField, BooleanField,
  10. SelectField, SelectMultipleField, validators)
  11. from flask_wtf import FlaskForm
  12. from enum import Enum
  13. class FlaskBBForm(FlaskForm):
  14. def populate_errors(self, errors):
  15. for (attribute, reason) in errors:
  16. self.errors.setdefault(attribute, []).append(reason)
  17. field = getattr(self, attribute, None)
  18. if field:
  19. field.errors.append(reason)
  20. class SettingValueType(Enum):
  21. string = 0
  22. integer = 1
  23. float = 3
  24. boolean = 4
  25. select = 5
  26. selectmultiple = 6
  27. def populate_settings_dict(form, settings):
  28. new_settings = {}
  29. for key, value in settings.items():
  30. try:
  31. # check if the value has changed
  32. if value == form[key].data:
  33. continue
  34. else:
  35. new_settings[key] = form[key].data
  36. except KeyError:
  37. pass
  38. return new_settings
  39. def populate_settings_form(form, settings):
  40. for key, value in settings.items():
  41. try:
  42. form[key].data = value
  43. except (KeyError, ValueError):
  44. pass
  45. return form
  46. # TODO(anr): clean this up
  47. def generate_settings_form(settings): # noqa: C901
  48. """Generates a settings form which includes field validation
  49. based on our Setting Schema."""
  50. class SettingsForm(FlaskBBForm):
  51. pass
  52. # now parse the settings in this group
  53. for setting in settings:
  54. field_validators = []
  55. if setting.value_type in {SettingValueType.integer,
  56. SettingValueType.float}:
  57. validator_class = validators.NumberRange
  58. elif setting.value_type == SettingValueType.string:
  59. validator_class = validators.Length
  60. # generate the validators
  61. if "min" in setting.extra:
  62. # Min number validator
  63. field_validators.append(
  64. validator_class(min=setting.extra["min"])
  65. )
  66. if "max" in setting.extra:
  67. # Max number validator
  68. field_validators.append(
  69. validator_class(max=setting.extra["max"])
  70. )
  71. # Generate the fields based on value_type
  72. # IntegerField
  73. if setting.value_type == SettingValueType.integer:
  74. setattr(
  75. SettingsForm, setting.key,
  76. IntegerField(setting.name, validators=field_validators,
  77. description=setting.description)
  78. )
  79. # FloatField
  80. elif setting.value_type == SettingValueType.float:
  81. setattr(
  82. SettingsForm, setting.key,
  83. FloatField(setting.name, validators=field_validators,
  84. description=setting.description)
  85. )
  86. # TextField
  87. elif setting.value_type == SettingValueType.string:
  88. setattr(
  89. SettingsForm, setting.key,
  90. TextField(setting.name, validators=field_validators,
  91. description=setting.description)
  92. )
  93. # SelectMultipleField
  94. elif setting.value_type == SettingValueType.selectmultiple:
  95. # if no coerce is found, it will fallback to unicode
  96. if "coerce" in setting.extra:
  97. coerce_to = setting.extra['coerce']
  98. else:
  99. coerce_to = str
  100. setattr(
  101. SettingsForm, setting.key,
  102. SelectMultipleField(
  103. setting.name,
  104. choices=setting.extra['choices'](),
  105. coerce=coerce_to,
  106. description=setting.description
  107. )
  108. )
  109. # SelectField
  110. elif setting.value_type == SettingValueType.select:
  111. # if no coerce is found, it will fallback to unicode
  112. if "coerce" in setting.extra:
  113. coerce_to = setting.extra['coerce']
  114. else:
  115. coerce_to = str
  116. setattr(
  117. SettingsForm, setting.key,
  118. SelectField(
  119. setting.name,
  120. coerce=coerce_to,
  121. choices=setting.extra['choices'](),
  122. description=setting.description)
  123. )
  124. # BooleanField
  125. elif setting.value_type == SettingValueType.boolean:
  126. setattr(
  127. SettingsForm, setting.key,
  128. BooleanField(setting.name, description=setting.description)
  129. )
  130. return SettingsForm