摘要:今天項目已經(jīng)能夠做一個簡單的后端服務(wù)了,在中新建一個表,就能自動提供的服務(wù)了。函數(shù)用來區(qū)分是查詢還是執(zhí)行操作。字段組合值組合,由元組轉(zhuǎn)換為數(shù)組配置相應(yīng)的占位符修改接口以字典形式提供參數(shù),占位符的形式為,只支持按主鍵進行修改。
關(guān)鍵點今天項目已經(jīng)能夠做一個簡單的后端服務(wù)了,在mysql中新建一個表,就能自動提供restful api的CURD服務(wù)了。
根據(jù)REST的四種動詞形式,動態(tài)調(diào)用相應(yīng)的CURD方法;
編寫REST與基礎(chǔ)數(shù)據(jù)庫訪問類之間的中間層(baseDao),實現(xiàn)從REST到數(shù)據(jù)訪問接口之間能用業(yè)務(wù)邏輯處理;
編寫基礎(chǔ)數(shù)據(jù)庫訪問類(dehelper),實現(xiàn)從字典形式的參數(shù)向SQL語句的轉(zhuǎn)換;
實現(xiàn)的rest-api實現(xiàn)了如下形式的rest-api
[GET]/rs/users/{id} [GET]/rs/users/key1/value1/key2/value2/.../keyn/valuen [POST]/rs/users [PUT]/rs/users/{id} [DELETE]/rs/users/{id}基礎(chǔ)數(shù)據(jù)庫訪問類
該類實現(xiàn)與pymysql庫的對接,提供標(biāo)準(zhǔn)CURD接口。
準(zhǔn)備數(shù)據(jù)庫表在數(shù)據(jù)庫對應(yīng)建立users表,腳本如下:
CREATE TABLE `users` ( `_id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) CHARACTER SET utf8mb4 DEFAULT "" COMMENT "標(biāo)題名稱", `phone` varchar(1024) DEFAULT "", `address` varchar(1024) DEFAULT NULL, `status` tinyint(4) DEFAULT "1" COMMENT "狀態(tài):0-禁;1-有效;9刪除", `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT "創(chuàng)建時間", PRIMARY KEY (`_id`), UNIQUE KEY `uuid` (`_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT="表";新建數(shù)據(jù)庫配置文件(configs.json)
數(shù)據(jù)連接配置,不入版本庫。
{ "db_config": { "db_host": "ip", "db_port": 1234, "db_username": "root", "db_password": "******", "db_database": "name", "db_charset": "utf8mb4" } }對接pymysql接口
用函數(shù)exec_sql封裝pymysql,提供統(tǒng)一訪問mysql的接口。is_query函數(shù)用來區(qū)分是查詢(R)還是執(zhí)行(CUD)操作。出錯處理折騰了好久,插入異常返回的錯誤形式與其它的竟然不一樣!返回參數(shù)是一個三元組(執(zhí)行是否成功,查詢結(jié)果或錯誤對象,查詢結(jié)果數(shù)或受影響的行數(shù))
with open("./configs.json", "r", encoding="utf-8") as json_file: dbconf = json.load(json_file)["db_config"] def exec_sql(sql, values, is_query=False): try: flag = False #是否有異常 error = {} #若異常,保存錯誤信息 conn = pymysql.connect(host=dbconf["db_host"], port=dbconf["db_port"], user=dbconf["db_username"], passwd=dbconf["db_password"], db=dbconf["db_database"], charset=dbconf["db_charset"]) with conn.cursor(pymysql.cursors.DictCursor) as cursor: num = cursor.execute(sql, values) #查詢結(jié)果集數(shù)量或執(zhí)行影響行數(shù) if is_query: #查詢?nèi)∷薪Y(jié)果 result = cursor.fetchall() else: #執(zhí)行提交 conn.commit() print("Sql: ", sql, " Values: ", values) except Exception as err: flag = True error = err print("Error: ", err) finally: conn.close() if flag: return False, error, num if "num" in dir() else 0 return True, result if "result" in dir() else "", num查詢接口
pymysql的查詢接口,可以接受數(shù)組,元組和字典,本查詢接口使用數(shù)組形式來調(diào)用。現(xiàn)在此接口只支持與條件組合參數(shù)。
def select(tablename, params={}, fields=[]): sql = "select %s from %s " % ("*" if len(fields) == 0 else ",".join(fields), tablename) ks = params.keys() where = "" ps = [] pvs = [] if len(ks) > 0: #存在查詢條件時,以與方式組合 for al in ks: ps.append(al + " =%s ") pvs.append(params[al]) where += " where " + " and ".join(ps) rs = exec_sql(sql+where, pvs, True) print("Result: ", rs) if rs[0]: return {"code": 200, "rows": rs[1], "total": rs[2]} else: return {"code": rs[1].args[0], "error": rs[1].args[1], "total": rs[2]}插入接口
以數(shù)組形式提供參數(shù),錯誤信息解析與其它接口不同。
def insert(tablename, params={}): sql = "insert into %s " % tablename ks = params.keys() sql += "(`" + "`,`".join(ks) + "`)" #字段組合 vs = list(params.values()) #值組合,由元組轉(zhuǎn)換為數(shù)組 sql += " values (%s)" % ",".join(["%s"]*len(vs)) #配置相應(yīng)的占位符 rs = exec_sql(sql, vs) if rs[0]: return {"code": 200, "info": "create success.", "total": rs[2]} else: return {"code": 204, "error": rs[1].args[0], "total": rs[2]}修改接口
以字典形式提供參數(shù),占位符的形式為:%(keyname)s,只支持按主鍵進行修改。
def update(tablename, params={}): sql = "update %s set " % tablename ks = params.keys() for al in ks: #字段與占位符拼接 sql += "`" + al + "` = %(" + al + ")s," sql = sql[:-1] #去掉最后一個逗號 sql += " where _id = %(_id)s " #只支持按主鍵進行修改 rs = exec_sql(sql, params) #提供字典參數(shù) if rs[0]: return {"code": 200, "info": "update success.", "total": rs[2]} else: return {"code": rs[1].args[0], "error": rs[1].args[1], "total": rs[2]}刪除接口
以字典形式提供參數(shù),占位符的形式為:%(keyname)s,只支持按主鍵進行刪除。
def delete(tablename, params={}): sql = "delete from %s " % tablename sql += " where _id = %(_id)s " rs = exec_sql(sql, params) if rs[0]: return {"code": 200, "info": "delete success.", "total": rs[2]} else: return {"code": rs[1].args[0], "error": rs[1].args[1], "total": rs[2]}中間層(baseDao)
提供默認的操作數(shù)據(jù)庫接口,實現(xiàn)基礎(chǔ)的業(yè)務(wù)邏輯,單表的CURD有它就足夠了。有復(fù)雜業(yè)務(wù)邏輯時,繼承它,進行擴展就可以了。
import dbhelper class BaseDao(object): def __init__(self, table): self.table = table def retrieve(self, params={}, fields=[], session={}): return dbhelper.select(self.table, params) def create(self, params={}, fields=[], session={}): if "_id" in params and len(params) < 2 or "_id" not in params and len(params) < 1: #檢測參數(shù)是否合法 return {"code": 301, "err": "The params is error."} return dbhelper.insert(self.table, params) def update(self, params={}, fields=[], session={}): if "_id" not in params or len(params) < 2: #_id必須提供且至少有一修改項 return {"code": 301, "err": "The params is error."} return dbhelper.update(self.table, params) def delete(self, params={}, fields=[], session={}): if "_id" not in params: #_id必須提供 return {"code": 301, "err": "The params is error."} return dbhelper.delete(self.table, params)動態(tài)調(diào)用CURD
根據(jù)客戶調(diào)用的rest方式不同,動態(tài)調(diào)用baseDao的相應(yīng)方法,這個很關(guān)鍵,實現(xiàn)了它才能自動分配方法調(diào)用,才能只需要建立一個數(shù)據(jù)表,就自動提供CURD基本訪問功能。還好,動態(tài)語言能很方便的實現(xiàn)這種功能,感慨一下,node.js更方便且符合習(xí)慣^_^
method = { "GET": "retrieve", "POST": "create", "PUT": "update", "DELETE": "delete" } getattr(BaseDao(table), method[request.method])(params, [], {})
說明:
table是前一章中解析出來的數(shù)據(jù)表名,這塊就是users;
method應(yīng)該是定義一個常量對象,對應(yīng)rest的動詞,因為對ypthon不熟,定義了一個變量先用著,查了下常量說明,看著好復(fù)雜;
request.method 客戶請求的實際rest動詞;
params是前一章中解析出來的參數(shù)對象;
完整代碼git clone https://github.com/zhoutk/pyrest.git cd pyrest export FLASK_APP=index.py flask run小結(jié)
至此,我們已經(jīng)實現(xiàn)了基本的框架功能,以后就是豐富它的羽翼。比如:session、文件上傳、跨域、路由改進(支持無縫切換操作數(shù)據(jù)庫的基類與子類)、參數(shù)驗證、基礎(chǔ)查詢功能增強(分頁、排序、模糊匹配等)。
感慨一下,好懷念在node.js中json對象的寫法,不用在key外加引號。
剛把基礎(chǔ)數(shù)據(jù)庫訪問類中的insert方法的參數(shù)形式改成了字典,結(jié)果異常信息也正常了,文章不再改動,有興趣者請自行查閱源代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/41052.html
摘要:項目介紹用語言來寫一個,數(shù)據(jù)庫使用。如此選擇,主要目的是針對中小規(guī)模的網(wǎng)絡(luò)應(yīng)用,能充分利用關(guān)系數(shù)據(jù)庫的種種優(yōu)勢,來實現(xiàn)豐富的現(xiàn)代互聯(lián)網(wǎng)應(yīng)用。經(jīng)搜索,還需要配置后面兩個環(huán)境變量才能正常運行,大概原因是版本與之間的區(qū)別。 一直在用node.js做后端,要逐步涉獵大數(shù)據(jù)范圍,注定繞不過python,因此決定把一些成熟的東西用python來重寫,一是開拓思路、通過比較來深入學(xué)習(xí)python;二...
摘要:今天我來和大家分享一下以及自動化生成工具的開發(fā)經(jīng)驗。代碼生成工具接著講講代碼生成工具,對于來講,有官方的代碼生成器,還有其他的同類開源項目比如?,F(xiàn)有的代碼生成器沒有可以開箱即用的,都需要去進行不少的修改。 前言 在開發(fā)工作中,經(jīng)常會遇到新產(chǎn)品、服務(wù)上線后,需要將其 API 編寫不同語言的 SDK。但不同語言 SDK 中都有很大一部分內(nèi)容是用來進行 API 的描述,而且這部分代碼量是最大...
摘要:今天我來和大家分享一下以及自動化生成工具的開發(fā)經(jīng)驗。代碼生成工具接著講講代碼生成工具,對于來講,有官方的代碼生成器,還有其他的同類開源項目比如。現(xiàn)有的代碼生成器沒有可以開箱即用的,都需要去進行不少的修改。 前言 在開發(fā)工作中,經(jīng)常會遇到新產(chǎn)品、服務(wù)上線后,需要將其 API 編寫不同語言的 SDK。但不同語言 SDK 中都有很大一部分內(nèi)容是用來進行 API 的描述,而且這部分代碼量是最大...
閱讀 1986·2021-09-09 09:33
閱讀 1116·2019-08-30 15:43
閱讀 2669·2019-08-30 13:45
閱讀 3310·2019-08-29 11:00
閱讀 860·2019-08-26 14:01
閱讀 3573·2019-08-26 13:24
閱讀 484·2019-08-26 11:56
閱讀 2692·2019-08-26 10:27