Le repo des sources pour le site web des JM2L
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

164 lignes
5.8 KiB

  1. try:
  2. from html import escape
  3. except ImportError:
  4. from cgi import escape
  5. #from wtforms import widgets
  6. from wtforms.widgets import HTMLString, html_params
  7. from wtforms.fields.core import Field
  8. from wtforms.compat import text_type, izip
  9. class MySelect(object):
  10. """
  11. Renders a select field.
  12. If `multiple` is True, then the `size` property should be specified on
  13. rendering to make the field useful.
  14. The field must provide an `iter_choices()` method which the widget will
  15. call on rendering; this method must yield tuples of
  16. `(value, label, selected)`.
  17. """
  18. def __init__(self, multiple=False):
  19. self.multiple = multiple
  20. def __call__(self, field, **kwargs):
  21. kwargs.setdefault('id', field.id)
  22. if self.multiple:
  23. kwargs['multiple'] = True
  24. html = ['<select %s>' % html_params(name=field.name, **kwargs)]
  25. last_group = None
  26. for group, val, label, selected in field.iter_choices():
  27. if group is None:
  28. html.append(self.render_option(val, label, selected))
  29. elif last_group != group:
  30. html.append(self.render_optgroup(last_group, group))
  31. html.append(self.render_option(val, label, selected))
  32. last_group=group
  33. else:
  34. html.append(self.render_option(val, label, selected))
  35. if last_group:
  36. html.append(self.render_optgroup(last_group, None))
  37. html.append('</select>')
  38. return HTMLString(''.join(html))
  39. @classmethod
  40. def render_option(cls, value, label, selected, **kwargs):
  41. if value is True:
  42. # Handle the special case of a 'True' value.
  43. value = text_type(value)
  44. options = dict(kwargs, value=value)
  45. if selected:
  46. options['selected'] = True
  47. return HTMLString('<option %s>%s</option>' % (html_params(**options), escape(text_type(label), quote=False)))
  48. @classmethod
  49. def render_optgroup(cls, previous_label, label, **kwargs):
  50. options = dict(kwargs)
  51. if previous_label is None:
  52. return HTMLString('<optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
  53. elif label is None:
  54. return HTMLString('</optgroup>')
  55. else:
  56. return HTMLString('</optgroup><optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
  57. class MyOption(object):
  58. """
  59. Renders the individual option from a select field.
  60. This is just a convenience for various custom rendering situations, and an
  61. option by itself does not constitute an entire field.
  62. """
  63. def __call__(self, field, **kwargs):
  64. return MySelect.render_option(field._value(), field.label.text, field.checked, **kwargs)
  65. class MySelectFieldBase(Field):
  66. #option_widget = widgets.Option()
  67. option_widget = MyOption()
  68. """
  69. Base class for fields which can be iterated to produce options.
  70. This isn't a field, but an abstract base class for fields which want to
  71. provide this functionality.
  72. """
  73. def __init__(self, label=None, validators=None, option_widget=None, **kwargs):
  74. super(MySelectFieldBase, self).__init__(label, validators, **kwargs)
  75. if option_widget is not None:
  76. self.option_widget = option_widget
  77. def iter_choices(self):
  78. """
  79. Provides data for choice widget rendering. Must return a sequence or
  80. iterable of (value, label, selected) tuples.
  81. """
  82. raise NotImplementedError()
  83. def __iter__(self):
  84. opts = dict(widget=self.option_widget, _name=self.name, _form=None, _meta=self.meta)
  85. for i, (value, label, checked) in enumerate(self.iter_choices()):
  86. opt = self._Option(label=label, id='%s-%d' % (self.id, i), **opts)
  87. opt.process(None, value)
  88. opt.checked = checked
  89. yield opt
  90. class _Option(Field):
  91. checked = False
  92. def _value(self):
  93. return text_type(self.data)
  94. class MySelectField(MySelectFieldBase):
  95. #widget = widgets.Select()
  96. widget = MySelect()
  97. def __init__(self, label=None, validators=None, coerce=text_type, choices=None, **kwargs):
  98. super(MySelectField, self).__init__(label, validators, **kwargs)
  99. self.coerce = coerce
  100. self.choices = choices
  101. def iter_choices(self):
  102. for choiceA, choiceB in self.choices:
  103. if isinstance(choiceB, (tuple, list)):
  104. # We should consider choiceA as an optgroup label
  105. group_label = choiceA
  106. for value, label in choiceB:
  107. yield (group_label, value, label, self.coerce(value) == self.data)
  108. else:
  109. value, label = choiceA, choiceB
  110. # Not an optgroup, let's fallback to classic usage
  111. yield (None, value, label, self.coerce(value) == self.data)
  112. def process_data(self, value):
  113. try:
  114. self.data = self.coerce(value)
  115. except (ValueError, TypeError):
  116. self.data = None
  117. def process_formdata(self, valuelist):
  118. if valuelist:
  119. try:
  120. self.data = self.coerce(valuelist[0])
  121. except ValueError:
  122. raise ValueError(self.gettext('Invalid Choice: could not coerce'))
  123. def pre_validate(self, form):
  124. for choiceA, choiceB in self.choices:
  125. if isinstance(choiceB, (tuple, list)):
  126. for value, label in choiceB:
  127. if self.data == value:
  128. break
  129. if self.data == value:
  130. break
  131. else:
  132. value, label = choiceA, choiceB
  133. if self.data == value:
  134. break
  135. else:
  136. raise ValueError(self.gettext('Not a valid choice'))