orm.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  95. def exist(self):
  96. sql_stmt = ("SELECT " + self._primary_key + " FROM " + self._table_name +
  97. " WHERE " + '{0} = %({0})s'.format(self._primary_key) + " LIMIT 1")
  98. cnx = db.cnxpool.get_connection()
  99. cursor = cnx.cursor(dictionary=True, buffered=True)
  100. try:
  101. cursor.execute(sql_stmt, self.__dict__)
  102. row = cursor.fetchone()
  103. finally:
  104. cursor.close()
  105. cnx.close()
  106. if isinstance(row, dict):
  107. return True
  108. return False
  109. def get_by(self, field):
  110. sql_stmt = ("SELECT " + ', '.join(self.__dict__.keys()) +
  111. " FROM " + self._table_name + " WHERE " + '{0} = %({0})s'.format(field) + " LIMIT 1")
  112. cnx = db.cnxpool.get_connection()
  113. cursor = cnx.cursor(dictionary=True, buffered=True)
  114. try:
  115. cursor.execute(sql_stmt, self.__dict__)
  116. row = cursor.fetchone()
  117. finally:
  118. cursor.close()
  119. cnx.close()
  120. if isinstance(row, dict):
  121. self.__dict__ = row
  122. else:
  123. ret = dict()
  124. ret['state'] = ji.Common.exchange_state(40401)
  125. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', self._primary_key.__str__()])
  126. raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))
  127. def exist_by(self, field):
  128. sql_field = field + ' = %(' + field + ')s'
  129. sql_stmt = ("SELECT " + self._primary_key + " FROM " + self._table_name + " WHERE " + sql_field + " LIMIT 1")
  130. cnx = db.cnxpool.get_connection()
  131. cursor = cnx.cursor(dictionary=True, buffered=True)
  132. try:
  133. cursor.execute(sql_stmt, self.__dict__)
  134. row = cursor.fetchone()
  135. finally:
  136. cursor.close()
  137. cnx.close()
  138. if isinstance(row, dict):
  139. return True
  140. return False
  141. @staticmethod
  142. def get_filter_keywords():
  143. # 指定参与过滤的关键字及其数据库对应字段类型
  144. """
  145. 使用示例
  146. return {
  147. 'name': FilterFieldType.STR.value,
  148. 'remark': FilterFieldType.STR.value,
  149. 'age': FilterFieldType.INT.value
  150. }
  151. """
  152. raise NotImplementedError()
  153. @classmethod
  154. def get_by_filter(cls, offset=0, limit=1000, order_by=None, order='asc', filter_str=''):
  155. if order_by is None:
  156. order_by = cls._primary_key
  157. sql_stmt = ("SELECT * FROM " + cls._table_name + " ORDER BY " + order_by + " " + order +
  158. " LIMIT %(offset)s, %(limit)s")
  159. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name)
  160. where_str = Filter.filter_str_to_sql(allow_keywords=cls.get_filter_keywords(), filter_str=filter_str)
  161. if where_str != '':
  162. sql_stmt = ("SELECT * FROM " + cls._table_name + " WHERE " + where_str + " ORDER BY " + order_by + " " +
  163. order + " LIMIT %(offset)s, %(limit)s")
  164. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name + " WHERE " + where_str)
  165. cnx = db.cnxpool.get_connection()
  166. cursor = cnx.cursor(dictionary=True, buffered=True)
  167. try:
  168. cursor.execute(sql_stmt, {'offset': offset, 'limit': limit})
  169. rows = cursor.fetchall()
  170. cursor.execute(sql_stmt_count)
  171. count = cursor.fetchone()
  172. return rows, count["count(" + cls._primary_key + ")"]
  173. finally:
  174. cursor.close()
  175. cnx.close()
  176. @staticmethod
  177. def get_allow_update_keywords():
  178. # 指定允许批量更新的字段
  179. """
  180. 使用示例
  181. return ['remark', 'age']
  182. """
  183. raise NotImplementedError()
  184. @classmethod
  185. def update_by_filter(cls, kv, filter_str=''):
  186. # 过滤掉不予支持批量更新的字段
  187. _kv = {}
  188. for k, v in kv.iteritems():
  189. if k in cls.get_allow_update_keywords():
  190. _kv[k] = v
  191. if _kv.__len__() < 1:
  192. return
  193. # set_str = ', '.join(map(lambda x: x + ' = %(' + x + ')s', _kv.keys()))
  194. # 上面为通过map实现的方式
  195. set_str = ', '.join(['{0} = %({0})s'.format(key) for key in _kv.keys()])
  196. where_str = Filter.filter_str_to_sql(allow_keywords=cls.get_filter_keywords(), filter_str=filter_str)
  197. sql_stmt = ("UPDATE " + cls._table_name + " SET " + set_str + " WHERE " + where_str)
  198. cnx = db.cnxpool.get_connection()
  199. cursor = cnx.cursor(dictionary=True, buffered=True)
  200. try:
  201. cursor.execute(sql_stmt, _kv)
  202. cnx.commit()
  203. finally:
  204. cursor.close()
  205. cnx.close()
  206. @classmethod
  207. def delete_by_filter(cls, filter_str=''):
  208. where_str = Filter.filter_str_to_sql(allow_keywords=cls.get_filter_keywords(), filter_str=filter_str)
  209. sql_stmt = ("DELETE FROM " + cls._table_name + " WHERE " + where_str)
  210. cnx = db.cnxpool.get_connection()
  211. cursor = cnx.cursor(dictionary=True, buffered=True)
  212. try:
  213. cursor.execute(sql_stmt)
  214. cnx.commit()
  215. finally:
  216. cursor.close()
  217. cnx.close()
  218. @staticmethod
  219. def get_allow_content_search_keywords():
  220. # 指定允许全文检索的字段
  221. """
  222. 使用示例
  223. return ['name', 'remark']
  224. """
  225. raise NotImplementedError()
  226. @classmethod
  227. def content_search(cls, offset=0, limit=1000, order_by=None, order='asc', keyword=''):
  228. if order_by is None:
  229. order_by = cls._primary_key
  230. _kv = dict()
  231. _kv = _kv.fromkeys(cls.get_allow_content_search_keywords(), '%{0}%'.format(keyword))
  232. where_str = ' OR '.join([k + ' LIKE %(' + k + ')s' for k in _kv.keys()])
  233. sql_stmt = ("SELECT * FROM " + cls._table_name + " WHERE " + where_str + " ORDER BY " + order_by + " " + order +
  234. " LIMIT %(offset)s, %(limit)s")
  235. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name + " WHERE " + where_str)
  236. _kv.update({'offset': offset, 'limit': limit})
  237. cnx = db.cnxpool.get_connection()
  238. cursor = cnx.cursor(dictionary=True, buffered=True)
  239. try:
  240. cursor.execute(sql_stmt, _kv)
  241. rows = cursor.fetchall()
  242. cursor.execute(sql_stmt_count, _kv)
  243. count = cursor.fetchone()
  244. return rows, count["count(" + cls._primary_key + ")"]
  245. finally:
  246. cursor.close()
  247. cnx.close()
  248. @classmethod
  249. def get_all(cls, order_by=None, order='asc'):
  250. if order_by is None:
  251. order_by = cls._primary_key
  252. sql_stmt = ("SELECT * FROM " + cls._table_name + " ORDER BY " + order_by + " " + order)
  253. sql_stmt_count = ("SELECT count(" + cls._primary_key + ") FROM " + cls._table_name)
  254. cnx = db.cnxpool.get_connection()
  255. cursor = cnx.cursor(dictionary=True, buffered=True)
  256. try:
  257. cursor.execute(sql_stmt)
  258. rows = cursor.fetchall()
  259. cursor.execute(sql_stmt_count)
  260. count = cursor.fetchone()
  261. return rows, count["count(" + cls._primary_key + ")"]
  262. finally:
  263. cursor.close()
  264. cnx.close()