orm.py 12 KB

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