国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

用python寫通用restful api service(二)

liangzai_cool / 2250人閱讀

摘要:今天項目已經能夠做一個簡單的后端服務了,在中新建一個表,就能自動提供的服務了。函數用來區分是查詢還是執行操作。字段組合值組合,由元組轉換為數組配置相應的占位符修改接口以字典形式提供參數,占位符的形式為,只支持按主鍵進行修改。

今天項目已經能夠做一個簡單的后端服務了,在mysql中新建一個表,就能自動提供restful api的CURD服務了。

關鍵點

根據REST的四種動詞形式,動態調用相應的CURD方法;

編寫REST與基礎數據庫訪問類之間的中間層(baseDao),實現從REST到數據訪問接口之間能用業務邏輯處理;

編寫基礎數據庫訪問類(dehelper),實現從字典形式的參數向SQL語句的轉換;

實現的rest-api

實現了如下形式的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}
基礎數據庫訪問類

該類實現與pymysql庫的對接,提供標準CURD接口。

準備數據庫表

在數據庫對應建立users表,腳本如下:

CREATE TABLE `users` (
  `_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) CHARACTER SET utf8mb4 DEFAULT "" COMMENT "標題名稱",
  `phone` varchar(1024) DEFAULT "",
  `address` varchar(1024) DEFAULT NULL,
  `status` tinyint(4) DEFAULT "1" COMMENT "狀態:0-禁;1-有效;9刪除",
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT "創建時間",
  PRIMARY KEY (`_id`),
  UNIQUE KEY `uuid` (`_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT="表";
新建數據庫配置文件(configs.json)

數據連接配置,不入版本庫。

{
  "db_config": {
    "db_host": "ip",
    "db_port": 1234,
    "db_username": "root",
    "db_password": "******",
    "db_database": "name",
    "db_charset": "utf8mb4"
  }
}
對接pymysql接口

用函數exec_sql封裝pymysql,提供統一訪問mysql的接口。is_query函數用來區分是查詢(R)還是執行(CUD)操作。出錯處理折騰了好久,插入異常返回的錯誤形式與其它的竟然不一樣!返回參數是一個三元組(執行是否成功,查詢結果或錯誤對象,查詢結果數或受影響的行數)

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)       #查詢結果集數量或執行影響行數
        if is_query:                                #查詢取所有結果
            result = cursor.fetchall()
        else:                                       #執行提交
            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的查詢接口,可以接受數組,元組和字典,本查詢接口使用數組形式來調用。現在此接口只支持與條件組合參數。

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]}
插入接口

以數組形式提供參數,錯誤信息解析與其它接口不同。

def insert(tablename, params={}):
    sql = "insert into %s " % tablename
    ks = params.keys()
    sql += "(`" + "`,`".join(ks) + "`)"               #字段組合
    vs = list(params.values())                        #值組合,由元組轉換為數組
    sql += " values (%s)" % ",".join(["%s"]*len(vs))  #配置相應的占位符
    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]}
修改接口

以字典形式提供參數,占位符的形式為:%(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)                       #提供字典參數
    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]}
刪除接口

以字典形式提供參數,占位符的形式為:%(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)

提供默認的操作數據庫接口,實現基礎的業務邏輯,單表的CURD有它就足夠了。有復雜業務邏輯時,繼承它,進行擴展就可以了。

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:      #檢測參數是否合法
            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)
動態調用CURD

根據客戶調用的rest方式不同,動態調用baseDao的相應方法,這個很關鍵,實現了它才能自動分配方法調用,才能只需要建立一個數據表,就自動提供CURD基本訪問功能。還好,動態語言能很方便的實現這種功能,感慨一下,node.js更方便且符合習慣^_^

    method = {
        "GET": "retrieve",
        "POST": "create",
        "PUT": "update",
        "DELETE": "delete"
    }
    
getattr(BaseDao(table), method[request.method])(params, [], {})

說明:

table是前一章中解析出來的數據表名,這塊就是users;

method應該是定義一個常量對象,對應rest的動詞,因為對ypthon不熟,定義了一個變量先用著,查了下常量說明,看著好復雜;

request.method 客戶請求的實際rest動詞;

params是前一章中解析出來的參數對象;

完整代碼
git clone https://github.com/zhoutk/pyrest.git
cd pyrest
export FLASK_APP=index.py
flask run
小結

至此,我們已經實現了基本的框架功能,以后就是豐富它的羽翼。比如:session、文件上傳、跨域、路由改進(支持無縫切換操作數據庫的基類與子類)、參數驗證、基礎查詢功能增強(分頁、排序、模糊匹配等)。
感慨一下,好懷念在node.js中json對象的寫法,不用在key外加引號。

補丁

剛把基礎數據庫訪問類中的insert方法的參數形式改成了字典,結果異常信息也正常了,文章不再改動,有興趣者請自行查閱源代碼。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41052.html

相關文章

  • pythonrestful api service(一)

    摘要:項目介紹用語言來寫一個,數據庫使用。如此選擇,主要目的是針對中小規模的網絡應用,能充分利用關系數據庫的種種優勢,來實現豐富的現代互聯網應用。經搜索,還需要配置后面兩個環境變量才能正常運行,大概原因是版本與之間的區別。 一直在用node.js做后端,要逐步涉獵大數據范圍,注定繞不過python,因此決定把一些成熟的東西用python來重寫,一是開拓思路、通過比較來深入學習python;二...

    LoftySoul 評論0 收藏0
  • 自動化代碼生成工具 Snips 開發實踐

    摘要:今天我來和大家分享一下以及自動化生成工具的開發經驗。代碼生成工具接著講講代碼生成工具,對于來講,有官方的代碼生成器,還有其他的同類開源項目比如。現有的代碼生成器沒有可以開箱即用的,都需要去進行不少的修改。 前言 在開發工作中,經常會遇到新產品、服務上線后,需要將其 API 編寫不同語言的 SDK。但不同語言 SDK 中都有很大一部分內容是用來進行 API 的描述,而且這部分代碼量是最大...

    only_do 評論0 收藏0
  • 自動化代碼生成工具 Snips 開發實踐

    摘要:今天我來和大家分享一下以及自動化生成工具的開發經驗。代碼生成工具接著講講代碼生成工具,對于來講,有官方的代碼生成器,還有其他的同類開源項目比如。現有的代碼生成器沒有可以開箱即用的,都需要去進行不少的修改。 前言 在開發工作中,經常會遇到新產品、服務上線后,需要將其 API 編寫不同語言的 SDK。但不同語言 SDK 中都有很大一部分內容是用來進行 API 的描述,而且這部分代碼量是最大...

    qc1iu 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<