orm.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import json
  4. import jimit as ji
  5. from mysql.connector import errorcode, errors
  6. from database import Database as db
  7. from models import Filter
  8. __author__ = 'James Iter'
  9. __date__ = '2017/3/23'
  10. __contact__ = 'james.iter.cn@gmail.com'
  11. __copyright__ = '(c) 2017 by James Iter.'
  12. class ORM(object):
  13. _table_name = None
  14. _primary_key = None
  15. def __init__(self):
  16. pass
  17. def create(self):
  18. sql_stmt = ("INSERT INTO " + self._table_name + " (" +
  19. ', '.join(filter(lambda _key: _key != self._primary_key, self.__dict__.keys())) +
  20. ") VALUES (" +
  21. ', '.join(['%({0})s'.format(key)
  22. for key in filter(lambda _key: _key != self._primary_key, self.__dict__.keys())]) + ")")
  23. cnx = db.cnxpool.get_connection()
  24. cursor = cnx.cursor(dictionary=True, buffered=True)
  25. try:
  26. cursor.execute(sql_stmt, self.__dict__)
  27. cnx.commit()
  28. except errors.IntegrityError, e:
  29. if e.errno == errorcode.ER_DUP_ENTRY:
  30. ret = dict()
  31. ret['state'] = ji.Common.exchange_state(40901)
  32. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', e.msg])
  33. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  34. finally:
  35. cursor.close()
  36. cnx.close()
  37. def update(self):
  38. if not self.exist():
  39. ret = dict()
  40. ret['state'] = ji.Common.exchange_state(40401)
  41. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', self._primary_key.__str__()])
  42. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  43. sql_stmt = ("UPDATE " + self._table_name + " SET " +
  44. ', '.join(['{0} = %({0})s'.format(key)
  45. for key in filter(lambda _key: _key != self._primary_key, self.__dict__.keys())]) +
  46. " WHERE " + '{0} = %({0})s'.format(self._primary_key))
  47. cnx = db.cnxpool.get_connection()
  48. cursor = cnx.cursor(dictionary=True, buffered=True)
  49. try:
  50. cursor.execute(sql_stmt, self.__dict__)
  51. cnx.commit()
  52. except errors.IntegrityError, e:
  53. if e.errno == errorcode.ER_DUP_ENTRY:
  54. ret = dict()
  55. ret['state'] = ji.Common.exchange_state(40901)
  56. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', e.msg])
  57. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  58. finally:
  59. cursor.close()
  60. cnx.close()
  61. def delete(self):
  62. if not self.exist():
  63. ret = dict()
  64. ret['state'] = ji.Common.exchange_state(40401)
  65. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', self._primary_key.__str__()])
  66. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  67. sql_stmt = ("DELETE FROM " + self._table_name + " WHERE " + '{0} = %({0})s'.format(self._primary_key))
  68. cnx = db.cnxpool.get_connection()
  69. cursor = cnx.cursor(dictionary=True, buffered=True)
  70. try:
  71. cursor.execute(sql_stmt, self.__dict__)
  72. cnx.commit()
  73. finally:
  74. cursor.close()
  75. cnx.close()
  76. def get(self):
  77. sql_stmt = ("SELECT " + ', '.join(self.__dict__.keys()) + " FROM " + self._table_name +
  78. " WHERE " + '{0} = %({0})s'.format(self._primary_key) +
  79. " LIMIT 1")
  80. cnx = db.cnxpool.get_connection()
  81. cursor = cnx.cursor(dictionary=True, buffered=True)
  82. try:
  83. cursor.execute(sql_stmt, self.__dict__)
  84. row = cursor.fetchone()
  85. finally:
  86. cursor.close()
  87. cnx.close()
  88. if isinstance(row, dict):
  89. self.__dict__ = row
  90. else:
  91. ret = dict()
  92. ret['state'] = ji.Common.exchange_state(40401)
  93. ret['state']['sub']['zh-cn'] = ': '.join([ret['state']['sub']['zh-cn'], self._primary_key.__str__(),
  94. self.__getattribute__(self._primary_key)])
  95. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  96. def exist(self):
  97. sql_stmt = ("SELECT " + self._primary_key + " FROM " + self._table_name +
  98. " WHERE " + '{0} = %({0})s'.format(self._primary_key) + " LIMIT 1")
  99. cnx = db.cnxpool.get_connection()
  100. cursor = cnx.cursor(dictionary=True, buffered=True)
  101. try:
  102. cursor.execute(sql_stmt, self.__dict__)
  103. row = cursor.fetchone()
  104. finally:
  105. cursor.close()
  106. cnx.close()
  107. if isinstance(row, dict):
  108. return True
  109. return False
  110. def get_by(self, field):
  111. sql_stmt = ("SELECT " + ', '.join(self.__dict__.keys()) +
  112. " FROM " + self._table_name + " WHERE " + '{0} = %({0})s'.format(field) + " LIMIT 1")
  113. cnx = db.cnxpool.get_connection()
  114. cursor = cnx.cursor(dictionary=True, buffered=True)
  115. try:
  116. cursor.execute(sql_stmt, self.__dict__)
  117. row = cursor.fetchone()
  118. finally:
  119. cursor.close()
  120. cnx.close()
  121. if isinstance(row, dict):
  122. self.__dict__ = row
  123. else:
  124. ret = dict()
  125. ret['state'] = ji.Common.exchange_state(40401)
  126. ret['state']['sub']['zh-cn'] = ': '.join([ret['state']['sub']['zh-cn'], self._primary_key.__str__(),
  127. self.__getattribute__(self._primary_key)])
  128. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  129. def exist_by(self, field):
  130. sql_field = field + ' = %(' + field + ')s'
  131. sql_stmt = ("SELECT " + self._primary_key + " FROM " + self._table_name + " WHERE " + sql_field + " LIMIT 1")
  132. cnx = db.cnxpool.get_connection()
  133. cursor = cnx.cursor(dictionary=True, buffered=True)
  134. try:
  135. cursor.execute(sql_stmt, self.__dict__)
  136. row = cursor.fetchone()
  137. finally:
  138. cursor.close()
  139. cnx.close()
  140. if isinstance(row, dict):
  141. return True
  142. return False
  143. @staticmethod
  144. def get_filter_keywords():
  145. # 指定参与过滤的关键字及其数据库对应字段类型
  146. """
  147. 使用示例
  148. return {
  149. 'name': FilterFieldType.STR.value,
  150. 'remark': FilterFieldType.STR.value,
  151. 'age': FilterFieldType.INT.value
  152. }
  153. """
  154. raise NotImplementedError()
  155. @classmethod
  156. def get_by_filter(cls, offset=0, limit=1000, order_by=None, order='asc', filter_str=''):
  157. if order_by is None:
  158. order_by = cls._primary_key
  159. sql_stmt = ("SELECT * FROM " + cls._table_name + " ORDER BY " + order_by + " " + order +
  160. " LIMIT %(offset)s, %(limit)s")
  161. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name)
  162. where_str = Filter.filter_str_to_sql(allow_keywords=cls.get_filter_keywords(), filter_str=filter_str)
  163. if where_str != '':
  164. sql_stmt = ("SELECT * FROM " + cls._table_name + " WHERE " + where_str + " ORDER BY " + order_by + " " +
  165. order + " LIMIT %(offset)s, %(limit)s")
  166. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name + " WHERE " + where_str)
  167. cnx = db.cnxpool.get_connection()
  168. cursor = cnx.cursor(dictionary=True, buffered=True)
  169. try:
  170. cursor.execute(sql_stmt, {'offset': offset, 'limit': limit})
  171. rows = cursor.fetchall()
  172. cursor.execute(sql_stmt_count)
  173. count = cursor.fetchone()
  174. return rows, count["count(" + cls._primary_key + ")"]
  175. finally:
  176. cursor.close()
  177. cnx.close()
  178. @staticmethod
  179. def get_allow_update_keywords():
  180. # 指定允许批量更新的字段
  181. """
  182. 使用示例
  183. return ['remark', 'age']
  184. """
  185. raise NotImplementedError()
  186. @classmethod
  187. def update_by_filter(cls, kv, filter_str=''):
  188. # 过滤掉不予支持批量更新的字段
  189. _kv = {}
  190. for k, v in kv.iteritems():
  191. if k in cls.get_allow_update_keywords():
  192. _kv[k] = v
  193. if _kv.__len__() < 1:
  194. return
  195. # set_str = ', '.join(map(lambda x: x + ' = %(' + x + ')s', _kv.keys()))
  196. # 上面为通过map实现的方式
  197. set_str = ', '.join(['{0} = %({0})s'.format(key) for key in _kv.keys()])
  198. where_str = Filter.filter_str_to_sql(allow_keywords=cls.get_filter_keywords(), filter_str=filter_str)
  199. sql_stmt = ("UPDATE " + cls._table_name + " SET " + set_str + " WHERE " + where_str)
  200. cnx = db.cnxpool.get_connection()
  201. cursor = cnx.cursor(dictionary=True, buffered=True)
  202. try:
  203. cursor.execute(sql_stmt, _kv)
  204. cnx.commit()
  205. finally:
  206. cursor.close()
  207. cnx.close()
  208. @classmethod
  209. def delete_by_filter(cls, filter_str=''):
  210. where_str = Filter.filter_str_to_sql(allow_keywords=cls.get_filter_keywords(), filter_str=filter_str)
  211. sql_stmt = ("DELETE FROM " + cls._table_name + " WHERE " + where_str)
  212. cnx = db.cnxpool.get_connection()
  213. cursor = cnx.cursor(dictionary=True, buffered=True)
  214. try:
  215. cursor.execute(sql_stmt)
  216. cnx.commit()
  217. finally:
  218. cursor.close()
  219. cnx.close()
  220. @staticmethod
  221. def get_allow_content_search_keywords():
  222. # 指定允许全文检索的字段
  223. """
  224. 使用示例
  225. return ['name', 'remark']
  226. """
  227. raise NotImplementedError()
  228. @classmethod
  229. def content_search(cls, offset=0, limit=1000, order_by=None, order='asc', keyword=''):
  230. if order_by is None:
  231. order_by = cls._primary_key
  232. _kv = dict()
  233. _kv = _kv.fromkeys(cls.get_allow_content_search_keywords(), '%{0}%'.format(keyword))
  234. where_str = ' OR '.join([k + ' LIKE %(' + k + ')s' for k in _kv.keys()])
  235. sql_stmt = ("SELECT * FROM " + cls._table_name + " WHERE " + where_str + " ORDER BY " + order_by + " " + order +
  236. " LIMIT %(offset)s, %(limit)s")
  237. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name + " WHERE " + where_str)
  238. _kv.update({'offset': offset, 'limit': limit})
  239. cnx = db.cnxpool.get_connection()
  240. cursor = cnx.cursor(dictionary=True, buffered=True)
  241. try:
  242. cursor.execute(sql_stmt, _kv)
  243. rows = cursor.fetchall()
  244. cursor.execute(sql_stmt_count, _kv)
  245. count = cursor.fetchone()
  246. return rows, count["count(" + cls._primary_key + ")"]
  247. finally:
  248. cursor.close()
  249. cnx.close()
  250. @classmethod
  251. def get_all(cls, order_by=None, order='asc'):
  252. if order_by is None:
  253. order_by = cls._primary_key
  254. sql_stmt = ("SELECT * FROM " + cls._table_name + " ORDER BY " + order_by + " " + order)
  255. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name)
  256. cnx = db.cnxpool.get_connection()
  257. cursor = cnx.cursor(dictionary=True, buffered=True)
  258. try:
  259. cursor.execute(sql_stmt)
  260. rows = cursor.fetchall()
  261. cursor.execute(sql_stmt_count)
  262. count = cursor.fetchone()
  263. return rows, count["count(" + cls._primary_key + ")"]
  264. finally:
  265. cursor.close()
  266. cnx.close()