個人第一個python web開發框架(33)——接口代碼重構

  前面ORM模塊咱們已經完成了開發,接下來要作的就是對項目代碼進行重構了。由於對底層數據庫操做模塊(db_helper.py)進行了改造,以前項目的接口代碼全都跑不起來了。python

  在寫ORM模塊時,咱們已經對產品接口的分頁查詢、新增、修改、獲取指定產品實體接口已經重構好了,還剩下刪除接口未完成web

 1 @delete('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     刪除指定記錄
 5     """
 6     # 編輯記錄
 7     sql = """delete from product where id=%s returning id"""
 8     vars = (id,)
 9     # 寫入數據庫
10     result = db_helper.write(sql, vars)
11     # 判斷是否提交成功
12     if result:
13         return web_helper.return_msg(0, '成功')
14     else:
15         return web_helper.return_msg(-1, "刪除失敗")

  若是前面代碼有認真學習的小夥伴看到這段代碼,要改爲ORM方式應該很容易實現了sql

  只須要將第7行到第10行替換對應的調用代碼就能夠了數據庫

 1 @delete('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     刪除指定記錄
 5     """
 6     # 實例化product表操做類ProductLogic
 7     _product_logic = product_logic.ProductLogic()
 8     result = _product_logic.delete_model(id)
 9     # 判斷是否提交成功
10     if result:
11         return web_helper.return_msg(0, '成功')
12     else:
13         return web_helper.return_msg(-1, "刪除失敗")

  首先是初始化產品邏輯層操做類,而後調用delete_model()這個方法就能夠了json

  當你習慣這種寫法之後,你會發現實現各個接口會變得很是的簡單與方便,開發速度比以前也提高了不少api

  產品分類相關接口(product_class.py)與產品相關接口(product.py)功能差很少,具體實現我就不一一講解了,你們能夠本身試試緩存

 

  產品分類的刪除分類接口你們會看到它的代碼與產品刪除接口差很少,不過多了一個該分類是否已經被引用的一個判斷,對於這個下面專門說明一下框架

 1 @delete('/api/product_class/<id:int>/')
 2 def callback(id):
 3     """
 4     刪除指定記錄
 5     """
 6     # 判斷該分類是否已經被引用,是的話不能直接刪除
 7     sql = """select count(*) as total from product where product_class_id=%s""" % (id,)
 8     # 讀取記錄
 9     result = db_helper.read(sql)
10     if result and result[0].get('total', -1) > 0:
11         return web_helper.return_msg(-1, "該分類已被引用,請清除對該分類的綁定後再來刪除")
12 
13     # 編輯記錄
14     sql = """delete from product_class where id=%s returning id"""
15     vars = (id,)
16     # 寫入數據庫
17     result = db_helper.write(sql, vars)
18     # 判斷是否提交成功
19     if result:
20         return web_helper.return_msg(0, '成功')
21     else:
22         return web_helper.return_msg(-1, "刪除失敗")

  這段代碼後半部分能夠參考產品的刪除接口實現,前半部分須要調用產品方法進行判斷處理。post

  在編寫時咱們會發現,咱們的ORM並無直接判斷記錄是否存在的方法,只有一個用於獲取指定條件記錄數的方法。學習

  通常來講,咱們在開發時發現ORM沒有本身想要的方法時,咱們須要作如下思考:

  1.有沒有替代能夠實現的方法存在

  2.該功能是不是經常使用的功能,可否封裝成公共方法,若是能夠就將它封裝到邏輯層基類(ORM模塊)中去,讓全部繼承的子類都擁有這個功能

  3.若是它只是對指定表單操做時纔用到,就將它封裝到該邏輯層子類,方便該子類要用到時能夠隨時調用

  這段代碼的要求是判斷指定的分類是否被產品引用,抽象出來的意思就是判斷指定條件的記錄是否存在,對於這個功能有開發經驗的小夥伴很容易判斷它是不少地方都有可能要用到的通用方法,因此咱們須要在ORM中增長一下這個方法。而咱們ORM已經存在get_count()這個獲取記錄數的方法存在了,咱們能夠經過調用這個方法來判斷記錄數量是否大於0,來得出指定條件的記錄是否存在這樣的結果。

    def exists(self, wheres):
        """檢查指定條件的記錄是否存在"""
        return self.get_count(wheres) > 0

  有了這個方法,咱們就能夠繼續對產品分類刪除接口進行改造了

 1 @delete('/api/product_class/<id:int>/')
 2 def callback(id):
 3     """
 4     刪除指定記錄
 5     """
 6     # 實例化product表操做類ProductLogic
 7     _product_logic = product_logic.ProductLogic()
 8     # 判斷該分類是否已經被引用,是的話不能直接刪除
 9     if _product_logic.exists('product_class_id=' + str(id)):
10         return web_helper.return_msg(-1, "該分類已被引用,請清除對該分類的綁定後再來刪除")
11 
12     # 實例化product_class表操做類product_class_logic
13     _product_class_logic = product_class_logic.ProductClassLogic()
14     result = _product_class_logic.delete_model(id)
15     # 判斷是否提交成功
16     if result:
17         return web_helper.return_msg(0, '成功')
18     else:
19         return web_helper.return_msg(-1, "刪除失敗")

  經過這個例子,你們在實際開發過程當中,能夠靈活的根據本身須要,來增長或改造對應的底層方法,積累你本身的底層框架代碼,那麼隨着開發時間的增長,你開發起各類功能來就會越加駕輕就熟了。

 

  細心的朋友會發現,ORM模塊的緩存部分,多了一個get_model_for_cache_of_where()方法,下面我來講明一下它的用途。

  咱們在開發時,除了經過主鍵id來獲取記錄實體之外,在有的數據表中,還會存在第二個主鍵,或多個主鍵的狀況,咱們須要經過這些主鍵來獲取對應的記錄實休,好比說管理員或用戶表中的登陸帳號字段;訂單表中的訂單編碼字段等。

  正常狀況下,咱們直接經過get_model()方法就能夠讀取對應的記錄了,若是咱們想減小數據庫的查詢,直接在緩存中如何使用呢?直接存取記錄實體,因爲這些額外的主鍵並無與ORM中的編輯與刪除操做關聯,即在進行編輯與刪除操做時不會同步更新用其餘主鍵存儲的實體內容,這樣就會產生髒數據。因此咱們能夠換一種思路來實現,咱們能夠將這些額外的主鍵和對應的值生成緩存組合key,裏面存儲對應的記錄實體id,也就是說在存儲記錄實體時,仍是使用原來的主鍵id存儲該實體,而後用額外主鍵和對應值生成緩存組合key中存儲主鍵id,在獲取記錄實體時,先用這個組合key提取對應的id,再用這個id來獲取記錄實體。這個說明好像有點繞,你們本身debug一下就很容易明白其中的原理了,下面看代碼:

 1     def get_model_for_cache_of_where(self, where):
 2         """
 3         經過條件獲取記錄實體————條件必須是額外的主鍵,也就是說記錄是惟一的(咱們常常須要使用key、編碼或指定條件來獲取記錄,這時能夠經過當前方法來獲取)
 4         :param where: 查詢條件
 5         :return: 記錄實體
 6         """
 7         # 生成實體緩存key
 8         model_cache_key = self.__table_name + encrypt_helper.md5(where)
 9         # 經過條件從緩存中獲取記錄id
10         pk = cache_helper.get(model_cache_key)
11         # 若是主鍵id存在,則直接從緩存中讀取記錄
12         if pk:
13             return self.get_model_for_cache(pk)
14 
15         # 不然從數據庫中獲取
16         result = self.get_model(where)
17         if result:
18             # 存儲條件對應的主鍵id值到緩存中
19             cache_helper.set(model_cache_key, result.get(self.__pk_name))
20             # 存儲記錄實體到緩存中
21             self.set_model_for_cache(result.get(self.__pk_name), result)
22             return result

  下面改造調用例子(請查看login.py第35行附近)

1     ##############################################################
2     ### 獲取登陸用戶記錄,並進行登陸驗證 ###
3     ##############################################################
4     sql = """select * from manager where login_name='%s'""" % (username,)
5     # 從數據庫中讀取用戶信息
6     manager_result = db_helper.read(sql)
7     # 判斷用戶記錄是否存在
8     if not manager_result:
9         return web_helper.return_msg(-1, '帳戶不存在')

  咱們能夠改造爲:

1     ##############################################################
2     ### 獲取登陸用戶記錄,並進行登陸驗證 ###
3     ##############################################################
4     _manager_logic = manager_logic.ManagerLogic()
5     # 從數據庫中讀取用戶信息
6     manager_result = _manager_logic.get_model_for_cache_of_where('login_name=' + string(username))
7     # 判斷用戶記錄是否存在
8     if not manager_result:
9         return web_helper.return_msg(-1, '帳戶不存在')

 

  還有登陸接口最底部,更新管理員最後登陸時、登陸ip和累加登陸次數須要改造,具體代碼以下:

1 ##############################################################
2     ### 更新用戶信息到數據庫 ###
3     ##############################################################
4     # 更新當前管理員最後登陸時間、Ip與登陸次數(字段說明,請看數據字典)
5     sql = """update manager set last_login_time=%s, last_login_ip=%s, login_count=login_count+1 where id=%s"""
6     # 組合更新值
7     vars = ('now()', ip, manager_id,)
8     # 寫入數據庫
9     db_helper.write(sql, vars)

  咱們能夠更改成:

 1     ##############################################################
 2     ### 更新用戶信息到數據庫 ###
 3     ##############################################################
 4     # 更新當前管理員最後登陸時間、Ip與登陸次數(字段說明,請看數據字典)
 5     fields = {
 6         'last_login_time': 'now()',
 7         'last_login_ip': string(ip),
 8         'login_count': 'login_count+1',
 9     }
10     # 寫入數據庫
11     _manager_logic.edit_model(manager_id, fields)

  對於字段值,若是爲字符串、具體時間、json等類型的,也就是說須要用單撇號括起來的,咱們就須要調用string_helper模塊的string方法進行轉換,它能夠爲變量增長單撇號,若是直接賦字符串值,生成的sql語句是沒有單撇號的,這裏要注意一下

  若是是數值類型,直接寫值就能夠了,固然直接賦字符串值也沒有關係,由於生成sql是不會自動添加單撇號的

  若是要賦postgresql系統變量,如now(),直接像上面這樣寫就能夠了

  若是字段是數值型,要讓它進行計算,直接像上面這樣寫也行,能夠是多個字段用加號連起來。固然你也能夠將字段時讀出來進行計算後再賦值提交也沒有問題

  具體操做須要你們本身多debug,多測試使用才知道怎麼應用到真實項目中。

 

 

  本文對應的源碼下載

 

版權聲明:本文原創發表於 博客園,做者爲 AllEmpty 本文歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然視爲侵權。

python開發QQ羣:669058475(本羣已滿)、733466321(能夠加2羣)    做者博客:http://www.cnblogs.com/EmptyFS/

相關文章
相關標籤/搜索