view.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import logging
  2. from flask_admin.model import BaseModelView
  3. from wtforms_appengine import db as wt_db
  4. from wtforms_appengine import ndb as wt_ndb
  5. from google.appengine.ext import db
  6. from google.appengine.ext import ndb
  7. from flask_wtf import Form
  8. from flask_admin.model.form import create_editable_list_form
  9. from .form import AdminModelConverter
  10. class NdbModelView(BaseModelView):
  11. """
  12. AppEngine NDB model scaffolding.
  13. """
  14. def get_pk_value(self, model):
  15. return model.key.urlsafe()
  16. def scaffold_list_columns(self):
  17. return sorted([k for (k, v) in self.model.__dict__.iteritems() if isinstance(v, ndb.Property)])
  18. def scaffold_sortable_columns(self):
  19. return [k for (k, v) in self.model.__dict__.iteritems() if isinstance(v, ndb.Property) and v._indexed]
  20. def init_search(self):
  21. return None
  22. def is_valid_filter(self):
  23. pass
  24. def scaffold_filters(self):
  25. # TODO: implement
  26. pass
  27. form_args = None
  28. model_form_converter = AdminModelConverter
  29. """
  30. Model form conversion class. Use this to implement custom field conversion logic.
  31. For example::
  32. class MyModelConverter(AdminModelConverter):
  33. pass
  34. class MyAdminView(ModelView):
  35. model_form_converter = MyModelConverter
  36. """
  37. def scaffold_form(self):
  38. form_class = wt_ndb.model_form(
  39. self.model(),
  40. base_class=Form,
  41. only=self.form_columns,
  42. exclude=self.form_excluded_columns,
  43. field_args=self.form_args,
  44. converter=self.model_form_converter(),
  45. )
  46. return form_class
  47. def scaffold_list_form(self, widget=None, validators=None):
  48. form_class = wt_ndb.model_form(
  49. self.model(),
  50. base_class=Form,
  51. only=self.column_editable_list,
  52. field_args=self.form_args,
  53. converter=self.model_form_converter(),
  54. )
  55. result = create_editable_list_form(Form, form_class, widget)
  56. return result
  57. def get_list(self, page, sort_field, sort_desc, search, filters,
  58. page_size=None):
  59. # TODO: implement filters (don't think search can work here)
  60. q = self.model.query()
  61. if sort_field:
  62. order_field = getattr(self.model, sort_field)
  63. if sort_desc:
  64. order_field = -order_field
  65. q = q.order(order_field)
  66. if not page_size:
  67. page_size = self.page_size
  68. results = q.fetch(page_size, offset=page * page_size)
  69. return q.count(), results
  70. def get_one(self, urlsafe_key):
  71. return ndb.Key(urlsafe=urlsafe_key).get()
  72. def create_model(self, form):
  73. try:
  74. model = self.model()
  75. form.populate_obj(model)
  76. model.put()
  77. except Exception as ex:
  78. if not self.handle_view_exception(ex):
  79. # flash(gettext('Failed to create record. %(error)s',
  80. # error=ex), 'error')
  81. logging.exception('Failed to create record.')
  82. return False
  83. else:
  84. self.after_model_change(form, model, True)
  85. return model
  86. def update_model(self, form, model):
  87. try:
  88. form.populate_obj(model)
  89. model.put()
  90. except Exception as ex:
  91. if not self.handle_view_exception(ex):
  92. # flash(gettext('Failed to update record. %(error)s',
  93. # error=ex), 'error')
  94. logging.exception('Failed to update record.')
  95. return False
  96. else:
  97. self.after_model_change(form, model, False)
  98. return True
  99. def delete_model(self, model):
  100. try:
  101. model.key.delete()
  102. except Exception as ex:
  103. if not self.handle_view_exception(ex):
  104. # flash(gettext('Failed to delete record. %(error)s',
  105. # error=ex),
  106. # 'error')
  107. logging.exception('Failed to delete record.')
  108. return False
  109. else:
  110. self.after_model_delete(model)
  111. return True
  112. class DbModelView(BaseModelView):
  113. """
  114. AppEngine DB model scaffolding.
  115. """
  116. def get_pk_value(self, model):
  117. return str(model.key())
  118. def scaffold_list_columns(self):
  119. return sorted([k for (k, v) in self.model.__dict__.iteritems() if isinstance(v, db.Property)])
  120. def scaffold_sortable_columns(self):
  121. # We use getattr() because ReferenceProperty does not specify a 'indexed' field
  122. return [k for (k, v) in self.model.__dict__.iteritems()
  123. if isinstance(v, db.Property) and getattr(v, 'indexed', None)]
  124. def init_search(self):
  125. return None
  126. def is_valid_filter(self):
  127. pass
  128. def scaffold_filters(self):
  129. # TODO: implement
  130. pass
  131. def scaffold_form(self):
  132. return wt_db.model_form(self.model())
  133. def get_list(self, page, sort_field, sort_desc, search, filters):
  134. # TODO: implement filters (don't think search can work here)
  135. q = self.model.all()
  136. if sort_field:
  137. if sort_desc:
  138. sort_field = "-" + sort_field
  139. q.order(sort_field)
  140. results = q.fetch(self.page_size, offset=page * self.page_size)
  141. return q.count(), results
  142. def get_one(self, encoded_key):
  143. return db.get(db.Key(encoded=encoded_key))
  144. def create_model(self, form):
  145. try:
  146. model = self.model()
  147. form.populate_obj(model)
  148. model.put()
  149. return model
  150. except Exception as ex:
  151. if not self.handle_view_exception(ex):
  152. # flash(gettext('Failed to create record. %(error)s',
  153. # error=ex), 'error')
  154. logging.exception('Failed to create record.')
  155. return False
  156. def update_model(self, form, model):
  157. try:
  158. form.populate_obj(model)
  159. model.put()
  160. return True
  161. except Exception as ex:
  162. if not self.handle_view_exception(ex):
  163. # flash(gettext('Failed to update record. %(error)s',
  164. # error=ex), 'error')
  165. logging.exception('Failed to update record.')
  166. return False
  167. def delete_model(self, model):
  168. try:
  169. model.delete()
  170. return True
  171. except Exception as ex:
  172. if not self.handle_view_exception(ex):
  173. # flash(gettext('Failed to delete record. %(error)s',
  174. # error=ex),
  175. # 'error')
  176. logging.exception('Failed to delete record.')
  177. return False
  178. def ModelView(model):
  179. if issubclass(model, ndb.Model):
  180. return NdbModelView(model)
  181. elif issubclass(model, db.Model):
  182. return DbModelView(model)
  183. else:
  184. raise ValueError("Unsupported model: %s" % model)