ajax.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. from flask_admin._compat import as_unicode, string_types
  2. from flask_admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
  3. from .tools import get_primary_key
  4. class QueryAjaxModelLoader(AjaxModelLoader):
  5. def __init__(self, name, model, **options):
  6. """
  7. Constructor.
  8. :param fields:
  9. Fields to run query against
  10. """
  11. super(QueryAjaxModelLoader, self).__init__(name, options)
  12. self.model = model
  13. self.fields = options.get('fields')
  14. if not self.fields:
  15. raise ValueError('AJAX loading requires `fields` to be specified for %s.%s' % (model, self.name))
  16. self._cached_fields = self._process_fields()
  17. self.pk = get_primary_key(model)
  18. def _process_fields(self):
  19. remote_fields = []
  20. for field in self.fields:
  21. if isinstance(field, string_types):
  22. attr = getattr(self.model, field, None)
  23. if not attr:
  24. raise ValueError('%s.%s does not exist.' % (self.model, field))
  25. remote_fields.append(attr)
  26. else:
  27. remote_fields.append(field)
  28. return remote_fields
  29. def format(self, model):
  30. if not model:
  31. return None
  32. return (getattr(model, self.pk), as_unicode(model))
  33. def get_one(self, pk):
  34. return self.model.get(**{self.pk: pk})
  35. def get_list(self, term, offset=0, limit=DEFAULT_PAGE_SIZE):
  36. query = self.model.select()
  37. stmt = None
  38. for field in self._cached_fields:
  39. q = field ** (u'%%%s%%' % term)
  40. if stmt is None:
  41. stmt = q
  42. else:
  43. stmt |= q
  44. query = query.where(stmt)
  45. if offset:
  46. query = query.offset(offset)
  47. return list(query.limit(limit).execute())
  48. def create_ajax_loader(model, name, field_name, options):
  49. prop = getattr(model, field_name, None)
  50. if prop is None:
  51. raise ValueError('Model %s does not have field %s.' % (model, field_name))
  52. # TODO: Check for field
  53. remote_model = prop.rel_model
  54. return QueryAjaxModelLoader(name, remote_model, **options)