orm.py 13 KB

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