隨著需要入庫(kù)的數(shù)據(jù)越來(lái)越多,這樣相應(yīng)的sql操作越來(lái)越多;
正好在做單元測(cè)試的時(shí)候看見laravel中對(duì)庫(kù)操作的封裝思想柿冲,用過(guò)感覺邏輯性很強(qiáng),索性拿過(guò)來(lái)兆旬;
基礎(chǔ):
FOR Python2.7
import MySQLdb
import MySQLdb.cursors
封裝思想:
- 封裝Base類假抄,即父類
- 封裝操作表(Table)類,即子類
- Table類繼承Base類,且在Table類中只操作當(dāng)前表宿饱,也就是說(shuō)每個(gè)表對(duì)應(yīng)一個(gè)Table類
- Table類類名稱的命名規(guī)則:類名即表名熏瞄,保持一致,這樣可以通過(guò)獲取當(dāng)前類名稱達(dá)到獲取表名的目的刑棵;
具體實(shí)現(xiàn):
Base.py
中
- 定義父類
Base
- 完成連接數(shù)據(jù)庫(kù)操作巴刻,并獲取游標(biāo)
cursor
- 封裝最基礎(chǔ)表操作:增刪改查及公共方法
class Base:
"""
mysql相關(guān)方法
connect:鏈接數(shù)據(jù)庫(kù)
creat_table:創(chuàng)建表
create datebase dbname;
"""
def __init__(self):
"""
鏈接數(shù)據(jù)庫(kù)
:param kwargs:
"""
self.db, self.cursor =self.__connect()
def __connect(self, database='', who='Null'):
"""鏈接數(shù)據(jù)庫(kù)"""
ip, username, password, database = self.__getConnectData(database, who)#此方法為的讀取配置文件的封裝方法
try:
self.db = MySQLdb.connect(
ip, username, password, database, charset='utf8',
cursorclass=MySQLdb.cursors.DictCursor)
return self.db, self.db.cursor()
except MySQLdb.Error as msg:
raise msg
def __sql_contact(self, **kwargs):
"""
構(gòu)造和拼接sql語(yǔ)句
:param data: 查詢字段
:param table: 表名
:param where: 條件
:param limit: 返回條數(shù)
:param order: 排序
:param group: 分組
:return:
"""
data = ''
table = ''
where = ''
limit = ''
order = ''
group = ''
if kwargs:
for key, value in kwargs.items():
if key =='data':
data = str(value)
if key =='table':
table = str(value)
if key =='where':
where = str(value)
if key =='limit':
limit = str(value)
if key =='order':
order = str(value)
if key =='group':
group = str(value)
where = ' WHERE ' + where if where else ''
limit = ' LIMIT ' + limit if limit else ''
order = ' ORDER BY ' + order if order else ''
group = ' GROUP BY ' + group if group else ''
data = data if data else '*'
sql = 'SELECT ' + data + ' FROM ' + table + where + group + order + limit
return sql
def query(self, sql):
"""
查詢表蛉签,且?guī)献侄蚊Q
:param
:param sql:輸出查詢語(yǔ)句
:return:返回字典
"""
try:
cur = self.cursor
cur.execute(sql)
index = cur.description
result = []
response = cur.fetchall()
if response:
for res in response:
row = {}
for i in range(len(index)):
row[index[i][0]] = res[index[i][0]]
result.append(row)
return result
else:
return {'status': '0', 'msg': 'result is Null'}
except Exception as msg:
print (msg)
raise
def select(self, **kwargs):
"""
查詢表
:param data: 查詢字段
:param table: 表名
:param where: 條件
:param limit: 返回條數(shù)
:param order: 排序
:param group: 分組
:return: 查詢結(jié)果
"""
sql = self.__sql_contact(**kwargs)
result = self.query(sql)
return result
......
Table類中todo.py
- 繼承Base類
- 獲取表名
- 重寫父類中方法
# coding=utf-8
__author__ = 'xcma'
import os
import sys
from Src.Function.Base import Base
class todo(Base):
def __init__(self):
Base.__init__(self)
self.table = self.__getTableName()
def __getTableName(self):
"""
返回當(dāng)前文件的名稱、文件名及路徑
:param is_path:
:return:
"""
return os.path.basename(__file__).split('.')[0]
def select_todo(self, data='', where='', limit='', order='', group=''):
kwargs = dict(data=data, table=self.table, where=where, limit=limit, order=order, group=group)
result = Base.select(self, **kwargs)
return result
注意:**kwargs的使用盡量放在內(nèi)部調(diào)用時(shí)使用沥寥,暴露在最外層的接口最好將必填參數(shù)全部暴露出來(lái)碍舍,這樣在外部調(diào)用的時(shí)候參數(shù)顯而易見,在內(nèi)部調(diào)用看起來(lái)很簡(jiǎn)潔邑雅;而且配置可變參數(shù)會(huì)更加靈活些片橡;
總結(jié):
- mysql類這樣封裝完以后,業(yè)務(wù)上需要操作哪個(gè)表淮野,就直接引用哪個(gè)表文件即可捧书,絲毫不用擔(dān)心表名是什么;
- 如果某個(gè)操作很常見骤星,則可以提到
Base
類中经瓷,這樣對(duì)各個(gè)表中的復(fù)用、重寫會(huì)很方便洞难;
@霧霾 -2016-12-16 22:01:09