widgets.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. from __future__ import division
  4. from __future__ import print_function
  5. from __future__ import unicode_literals
  6. from django.forms import widgets
  7. from django.template import loader, Context
  8. from django.utils.encoding import force_text
  9. from rapid.wrappers import ModelData
  10. _templates_root = 'rapid/widgets/'
  11. class RapidReadOnly(widgets.Widget):
  12. def render(self, name, value, attrs=None):
  13. hidden = '<input type="hidden" name="%s" value="%s" ' % (name, value if value else "")
  14. for a in attrs.keys():
  15. hidden += '%s="%s" ' % (a, attrs[a])
  16. hidden += '>'
  17. return '<span class="data-value">%s</span>%s\n' % (force_text(value), hidden)
  18. def value_from_datadict(self, data, files, name):
  19. return data.get(name)
  20. def getRapidReadonlyRelation(model, originator):
  21. class RapidRelationReadOnly(widgets.Widget):
  22. def render(self, name, value, attrs=None):
  23. hidden = '<input type="hidden" name="%s" value="%s" ' % (name, value if value else "")
  24. for a in attrs.keys():
  25. hidden += '%s="%s" ' % (a, attrs[a])
  26. hidden += '>'
  27. if hasattr(value, '__iter__'):
  28. obj = model.default_manager().filter(pk__in=value)
  29. ret = ''
  30. for o in obj:
  31. ret += '<span class="data-value multiple">%s</span>\n' % force_text(o)
  32. ret += hidden
  33. return ret
  34. else:
  35. if value:
  36. obj = model.default_manager().get(pk=value)
  37. else:
  38. obj = ""
  39. return '<span class="data-value">%s</span>%s\n' % (force_text(obj), hidden)
  40. def value_from_datadict(self, data, files, name):
  41. return originator
  42. return RapidRelationReadOnly
  43. class RapidSelector(widgets.Select):
  44. """
  45. Selects one of the target crud type.
  46. For ForeignKeyFields and OneToOneFields.
  47. If the target is dependent (that means, has only
  48. value when linked with this object), only displays
  49. an edition link.
  50. """
  51. def __init__(self, relation, *args, **kwargs):
  52. super(RapidSelector, self).__init__(*args, **kwargs)
  53. self.relation = relation
  54. self.allow_multiple_selected = relation.is_multiple()
  55. self.remove_deselected = relation.is_existential_dependency()
  56. def render(self, name, value, attrs=None, choices=()):
  57. tp_id = attrs.get('id', name)
  58. related = self.relation.related_model()
  59. if self.allow_multiple_selected:
  60. if value:
  61. v = ",".join([str(x) for x in value])
  62. selected = related.default_manager().filter(pk__in=value)
  63. else:
  64. v = ""
  65. selected = []
  66. else:
  67. if value:
  68. v = str(value)
  69. selected = related.default_manager().get(pk=value)
  70. else:
  71. v = ""
  72. selected = ""
  73. select_url = related.select_url()
  74. if self.allow_multiple_selected:
  75. icon = 'fa-times'
  76. if self.remove_deselected:
  77. icon = 'fa-trash-o'
  78. else:
  79. icon = 'fa-search'
  80. c = Context({'id': tp_id, 'name': name, 'value': v, 'selected': selected, 'icon': icon,
  81. 'select_url': select_url, 'multiple': self.allow_multiple_selected})
  82. if self.allow_multiple_selected:
  83. t = loader.get_template(_templates_root + 'multiple-selector.html')
  84. else:
  85. t = loader.get_template(_templates_root + 'single-selector.html')
  86. return t.render(c)
  87. def value_from_datadict(self, data, files, name):
  88. val = data.get(name)
  89. if self.allow_multiple_selected:
  90. if val:
  91. return [int(x) for x in val.split(",") if x]
  92. return []
  93. else:
  94. if val:
  95. return int(val)
  96. return None
  97. def rapid_alternatives_widget(alternatives, selector):
  98. class RapidAlternativeFormsWidget(widgets.Widget):
  99. def render(self, name, value, attrs=None):
  100. attrs = attrs if attrs else []
  101. c = Context({'name': name,
  102. 'value': value,
  103. 'attrs': attrs,
  104. 'alternatives': alternatives.values(),
  105. 'selector': selector,
  106. })
  107. t = loader.get_template(_templates_root + 'alternativeForms.html')
  108. return t.render(c)
  109. def value_from_datadict(self, data, files, name):
  110. ct_id = data.get(selector)
  111. if not ct_id:
  112. return None
  113. return alternatives.get(int(ct_id))[1]
  114. return RapidAlternativeFormsWidget
  115. def rapid_dependent_widget(model_data, form, has_instance, is_mutiple):
  116. class RapidDependentWidget(widgets.Widget):
  117. # What to ask:
  118. # Is it optional? Yep, if it's dependent, it must be optional
  119. # Is it multiple? In is_multiple
  120. def render(self, name, value, attrs=None):
  121. attrs = attrs if attrs else []
  122. c = Context({'name': name,
  123. 'value': value,
  124. 'attrs': attrs,
  125. 'model': model_data,
  126. 'formset': form,
  127. }) if is_mutiple else Context (
  128. {'name': name,
  129. 'value': value,
  130. 'attrs': attrs,
  131. 'model': model_data,
  132. 'form': form,
  133. 'present': has_instance,
  134. })
  135. t = loader.get_template(_templates_root + ('multipleDependent.html' if
  136. is_mutiple else 'singleDependent.html'))
  137. return t.render(c)
  138. def value_from_datadict(self, data, files, name):
  139. # Might return:
  140. # None of model object if not is_multiple
  141. # [] ot list of model objects if is_multiple
  142. if is_mutiple:
  143. list_includes = [x for x in range(0, len(form)) if data.get("includes_" + form.prefix + "-" + str(x))]
  144. return (form, list_includes)
  145. else:
  146. s = data.get("includes_" + name)
  147. if s is None:
  148. return None
  149. else:
  150. return form
  151. return RapidDependentWidget