wrappers.py 10 KB

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