wrappers.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. # -*- coding: utf-8 -*-
  2. __author__ = 'marcos.medeiros'
  3. from rapid.registry import registry, Action
  4. from rapid import filters
  5. import itertools
  6. from django.db import models
  7. class InstanceData:
  8. def __init__(self, instance, request=None, excludes=None, creator=None, fields=None):
  9. excludes = [] if excludes is None else excludes
  10. self.model = ModelData(type(instance), request, excludes, creator, fields)
  11. self.instance = instance
  12. self.request = request
  13. self.excludes = excludes if excludes else []
  14. self.creator = creator
  15. self._fields = fields if fields else self.model.fields()
  16. def values(self):
  17. o = self.instance
  18. for f in self.model.fields():
  19. if f.is_relation:
  20. yield self._value_of_field(o, f)
  21. else:
  22. yield self._value_of_field(o, f)
  23. def _value_of_field(self, instance, field):
  24. """
  25. Retorna o valor do campo dado na instância informada.
  26. ::return Uma tupla, onde o primeiro elemento é o valor informado, o
  27. segundo elemento é um booleano que informa se o valor é iteravel ou não
  28. e o terceiro elemento é uma sequencia de URLs para os itens do primeiro elemento,
  29. ou um valor falso caso não haja links.
  30. """
  31. if hasattr(instance, field.bare_name()):
  32. v = getattr(instance, field.bare_name())
  33. else: # Many to many relations without value may disappear
  34. return [], True
  35. if hasattr(v, '__iter__'):
  36. return (v, ()), True
  37. if hasattr(v, 'all'):
  38. return [(x, InstanceData(x, self.request, creator=(self, field))) for x in v.all()], True
  39. if isinstance(v, models.Model):
  40. return (v, InstanceData(v, self.request, creator=(self, field))), False
  41. return (v, ()), False
  42. def fields_and_values(self):
  43. for field in self.model.fields():
  44. value, is_multiple = self._value_of_field(self.instance, field)
  45. yield field, value, is_multiple
  46. def is_controlled(self):
  47. return self.model.is_controlled()
  48. def can_read(self):
  49. if self.can_write():
  50. return True
  51. vw = registry.model_entry(self.model.model).permission_set(self.request)
  52. if vw:
  53. return vw.filter(pk=self.instance.pk).exists()
  54. return False
  55. def can_write(self):
  56. ed = registry.model_entry(self.model.model)['edit'].permission_set(self.request)
  57. if ed:
  58. return ed.filter(pk=self.instance.pk).exists()
  59. return False
  60. def view_url(self):
  61. return registry.get_url_of_action(self.model.model, "view", pk=self.instance.pk)
  62. def edit_url(self):
  63. url = registry.get_url_of_action(self.model.model, "edit", pk=self.instance.pk)
  64. by = self.creator
  65. if by:
  66. dt, fd = by
  67. if fd.one_to_one or fd.one_to_many:
  68. # Este objeto depende do parent.
  69. # Não posso editar esta relação
  70. return url + "?default=" + fd.field.name + ":" + str(dt.object.pk)
  71. if fd.many_to_one or fd.many_to_many:
  72. return url
  73. return url
  74. def remove_url(self):
  75. return registry.get_url_of_action(self.model.model, "delete", pk=self.instance.pk)
  76. def create_url(self):
  77. return registry.get_url_of_action(self.model.model, "add")
  78. def list_url(self):
  79. return registry.get_url_of_action(self.model.model, "list")
  80. def select_url(self):
  81. return registry.get_url_of_action(self.model.model, "select")
  82. def actions(self):
  83. acts = registry.model_entry(self.model.model)
  84. if self.request:
  85. for a in acts.values():
  86. if a.permission_set(self.request) and\
  87. a.permission_set(self.request).filter(pk=self.instance.pk).exists() and\
  88. a.action.visibility > Action.Visibility.hidden:
  89. yield (a, a.get_url(self.instance))
  90. def model_actions(self):
  91. for (a, u) in self.actions():
  92. if not a.action.query_parameters:
  93. yield (a, u)
  94. def instance_actions(self):
  95. for (a, u) in self.actions():
  96. if a.action.query_parameters:
  97. yield (a, u)
  98. def list_actions(self):
  99. for (a, u) in self.instance_actions():
  100. if a.action.visibility == Action.Visibility.list:
  101. yield (a, u)
  102. def has_permission(self, request, action_name):
  103. m = registry.model_entry(self.model.model).get(action_name)
  104. if m:
  105. return m.permission_set(request) and\
  106. m.permission_set(request).filter(pk=self.instance.pk).exists()
  107. return False
  108. def __unicode__(self):
  109. return unicode(self.instance)
  110. def __str__(self):
  111. return str(self.model) + ': ' + str(self.instance.pk)
  112. class ModelData:
  113. def __init__(self, model, request=None, excludes=None, creator=None, fields=None):
  114. excludes = [] if excludes is None else excludes
  115. self.model = model
  116. self.request = request
  117. self.excludes = excludes if excludes else []
  118. self.creator = creator
  119. self._fields = [self.field_by_name(f) for f in fields] if fields else self.all_fields()
  120. def model_name(self):
  121. return unicode(self.model._meta.verbose_name)
  122. def model_name_plural(self):
  123. return unicode(self.model._meta.verbose_name_plural)
  124. def default_manager(self):
  125. return self.model._default_manager
  126. def all_fields(self):
  127. relations = []
  128. for f in itertools.chain(self.local_fields(), self.related_fields()):
  129. if f.is_relation():
  130. relations.append(f)
  131. else:
  132. if f.name not in self.excludes:
  133. yield f
  134. for f in relations:
  135. if f.name not in self.excludes:
  136. yield f
  137. def fields(self):
  138. for f in self._fields:
  139. yield f
  140. def local_fields(self):
  141. for f in self.model._meta.local_fields:
  142. if f.name not in self.excludes:
  143. yield FieldData(f, self.request)
  144. for f in self.model._meta.local_many_to_many:
  145. if f.name not in self.excludes:
  146. yield FieldData(f, self.request)
  147. def related_fields(self):
  148. for f in self.model._meta.get_all_related_objects():
  149. yield FieldData(f, self.request)
  150. def is_controlled(self):
  151. return registry.is_controlled(self.model)
  152. def can_read(self):
  153. if self.can_write():
  154. return True
  155. vw = registry.model_entry(self.model)['view'].permission_set(self.request)
  156. if vw:
  157. return vw.exists()
  158. return False
  159. def can_write(self):
  160. ed = registry.model_entry(self.model)['edit'].permission_set(self.request)
  161. if ed:
  162. return ed.exists()
  163. return False
  164. def create_url(self):
  165. return registry.get_url_of_action(self.model, "add")
  166. def list_url(self):
  167. return registry.get_url_of_action(self.model, "list")
  168. def select_url(self):
  169. return registry.get_url_of_action(self.model, "select")
  170. def actions(self):
  171. acts = registry.model_entry(self.model)
  172. if self.request:
  173. for a in acts.values():
  174. if a.permission_set(self.request) and\
  175. a.permission_set(self.request).exists() and\
  176. not a.action.query_parameters and\
  177. a.action.visibility > Action.Visibility.hidden:
  178. yield (a, a.get_url())
  179. def has_permission(self, request, action_name):
  180. m = registry.model_entry(self.model).get(action_name)
  181. if m:
  182. return m.permission_set(request) and\
  183. m.permission_set(request).exists()
  184. return False
  185. def field_by_name(self, field_name):
  186. return FieldData(self.model._meta.get_field(field_name), self.request)
  187. def __unicode__(self):
  188. return unicode(self.model)
  189. def __str__(self):
  190. return 'Model: ' + str(self.model)
  191. class FieldData:
  192. def __init__(self, field, request=None):
  193. self.field = field
  194. self.request = request
  195. @classmethod
  196. def from_model(cls, model, field_name):
  197. ff = ModelData(model).fields()
  198. for f in ff:
  199. if f.bare_name() == unicode(field_name):
  200. return f
  201. return None
  202. def bare_name(self):
  203. return unicode(self.field.name)
  204. def name(self):
  205. if hasattr(self.field, "verbose_name"):
  206. return unicode(self.field.verbose_name)
  207. return unicode(self.field.name)
  208. def name_plural(self):
  209. if hasattr(self.field, "verbose_name_plural"):
  210. return unicode(self.field.verbose_name_plural)
  211. return self.name() + "s"
  212. def is_relation(self):
  213. return self.field.is_relation
  214. def is_multiple(self):
  215. if not self.is_relation():
  216. return False
  217. if self.field.one_to_many:
  218. return True
  219. if self.field.many_to_many:
  220. return True
  221. return False
  222. def related_model(self):
  223. if hasattr(self.field, "related_model"):
  224. return ModelData(self.field.related_model)
  225. if hasattr(self.field, "to"):
  226. return ModelData(self.field.to)
  227. return None
  228. def is_weak(self):
  229. if not self.is_relation():
  230. return False
  231. f = self.field
  232. if hasattr(f, "many_to_many") and f.many_to_many:
  233. return False
  234. if hasattr(f, "many_to_one") and self.field.many_to_one:
  235. return False
  236. if hasattr(self.field, "get_related_field"):
  237. o = self.field.get_related_field
  238. if self.field.one_to_one or self.field.one_to_many:
  239. if hasattr(o, "required"):
  240. return o.required
  241. return True
  242. if isinstance(f, models.ForeignKey):
  243. return self.related_model()._meta.pk.name
  244. return False
  245. def filter_html(self):
  246. return filters.Filter.selection_type_html(self, self.request)
  247. def __str__(self):
  248. return self.bare_name()
  249. class ValueData:
  250. def __init__(self, value, field):
  251. self.value = value
  252. self.field = field
  253. def can_view(self):
  254. if self.field.is_relation():
  255. o = self.field.related_model()
  256. return registry.is_controlled(o)
  257. return False
  258. def is_multiple(self):
  259. return self.field.is_multiple()
  260. def __str__(self):
  261. return str(self.field) + ': ' + str(self.value)