接下來咱們要封裝的是修改記錄模塊。python
先上產品信息編輯接口代碼web
1 @put('/api/product/<id:int>/') 2 def callback(id): 3 """ 4 修改記錄 5 """ 6 name = web_helper.get_form('name', '產品名稱') 7 code = web_helper.get_form('code', '產品編碼') 8 product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '產品分類')) 9 standard = web_helper.get_form('standard', '產品規格') 10 quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保質期') 11 place_of_origin = web_helper.get_form('place_of_origin', '產地') 12 front_cover_img = web_helper.get_form('front_cover_img', '封面圖片') 13 content = web_helper.get_form('content', '產品描述', is_check_special_char=False) 14 # 防sql注入攻擊處理 15 content = string_helper.filter_str(content, "'") 16 # 防xss攻擊處理 17 content = string_helper.clear_xss(content) 18 is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否啓用')) 19 20 # 組成編輯Sql 21 sql = """ 22 update product 23 set name=%s, code=%s, product_class_id=%s, standard=%s, quality_guarantee_period=%s, 24 place_of_origin=%s, front_cover_img=%s, content=%s, is_enable=%s 25 where id=%s returning id""" 26 vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content, is_enable, id) 27 # 寫入數據庫 28 result = db_helper.write(sql, vars) 29 # 判斷是否提交成功 30 if result and result[0].get('id'): 31 return web_helper.return_msg(0, '成功') 32 else: 33 return web_helper.return_msg(-1, "提交失敗")
第21行到25行,是咱們經常使用修改記錄的sql語句,它與插入記錄差異比較大,但也有類似的地方,那就是都是字段與值一一對應,咱們一樣可使用字典的方式將它作爲ORM的參數值,在ORM中進行轉換處理,組合成對應的sql語句。sql
操做步驟:數據庫
1.將新增記錄時的字段名與值,使用字典方式存儲起來api
2.將字典作爲參數傳給ORM編輯記錄方法數組
3.編輯記錄方法接收到參數之後,使用for循環,將字段名提取出來,生成sql編輯字段名、數組和字典替換數組,即:update table_name set 字段名=值,字段名=值... where 條件,這裏須要將字典中的字段名提取出來組合成「字段名=值,字段名=值...」這樣的串app
這個步驟看起來跟新增記錄差很少,只是生成sql的結果不同而已。xss
一樣的,咱們看看產品記錄編輯的例子,方便進行理解post
例如:咱們須要修改產品Id爲2的記錄,將它的名稱和產品詳情進行更改,咱們能夠將更改內容組合成一個字典單元測試
fields = { 'name': "'產品名稱'", 'content': "'產品詳情'", }
而後能夠經過for循環,將字典參數進行處理,提取出來存儲到list中
# 拼接字段與值 field_list = [key + ' = %(' + key + ')s' for key in fields.keys()]
咱們一樣使用for循環,遍歷全部字典內容,將它們提取出來進行組合。可能有朋友對上面這個for語句不太理解,我將它分解一下
field_list = [] for key in fields.keys(): field_list.append(key + ' = %(' + key + ')s')
for循環是python中應用最多的語句之一,它經過能夠將很複雜的須要不少代碼才能實現的語句,用一行語句將它實現出來,若是你能熟練掌握,你會發現它不但能簡化代碼,同時也提升了代碼的可讀性。
執行完後,field_list的值爲:
field_list = ['content = %(content)s', 'name = %(name)s']
而後咱們設置一個sql字符串拼接字典,將表名、字段名字符串與值字符串存儲進去,在存儲前使用join方式進行拼接,生成用逗號分隔的字符串
# 設置sql拼接字典 parameter = { 'table_name': self.__table_name, 'field_list': ','.join(field_list) }
執行後生成的值爲:
parameter = {'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product'}
因爲是編輯記錄,因此咱們一般要指定編輯記錄的條件,好比編輯id=1的記錄,或者更新全部記錄,這時就不須要指定條件,因此咱們還須要添加條件進來
# 若是存在更新條件,則將條件添加到sql拼接更換字典中 if wheres: parameter['wheres'] = ' where ' + wheres else: parameter['wheres'] = ''
執行後parameter值爲:
parameter = {'wheres': ' where id=2', 'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product'}
在執行更新操做時,咱們也常常會指定返回記錄的字段值回來使用。好比說:咱們要更新id爲2的記錄,將它設置爲禁用狀態,而後須要同步更新該分類記錄的產品數量,正常來講咱們須要執行修改操做之後,還須要將記錄查詢出來,而後獲取它的分類id,而後再去更新該分類的產品數量,而postgresql因爲擁有returning,因此咱們只須要將分類id放在returning語句中就能夠了,執行更新操做後會將分類id同時返回回來給咱們使用。
# 若是有指定返回參數,則添加 if returning: parameter['returning'] = ', ' + returning else: parameter['returning'] = ''
執行後parameter值爲:
parameter = {'wheres': ' where id=2', 'field_list': 'content = %(content)s,name = %(name)s', 'table_name': 'product', 'returning': ', product_class_id'}
而後將它們與編輯sql合成
sql = "update %(table_name)s set %(field_list)s %(wheres)s returning id %(returning)s" % parameter
執行後sql值爲:
'update product set content = %(content)s,name = %(name)s where id=1 returning id , product_class_id'
最後將它與最開始提交的字典參數進行合成
sql = sql % fields
生成最終可執行的sql語句
"update product set content = '產品詳情',name = '產品名稱' where id=2 returning id , product_class_id"
完整代碼
1 def edit(self, fields, wheres='', returning=''): 2 """批量編輯數據庫記錄""" 3 ### 拼接sql語句 ### 4 # 拼接字段與值 5 field_list = [key + ' = %(' + key + ')s' for key in fields.keys()] 6 # 設置sql拼接字典 7 parameter = { 8 'table_name': self.__table_name, 9 'field_list': ','.join(field_list) 10 } 11 # 若是存在更新條件,則將條件添加到sql拼接更換字典中 12 if wheres: 13 parameter['wheres'] = ' where ' + wheres 14 else: 15 parameter['wheres'] = '' 16 17 # 若是有指定返回參數,則添加 18 if returning: 19 parameter['returning'] = ', ' + returning 20 else: 21 parameter['returning'] = '' 22 23 # 生成sql語句 24 sql = "update %(table_name)s set %(field_list)s %(wheres)s returning id %(returning)s" % parameter 25 sql = sql % fields 26 27 return self.execute(sql)
你們本身多debug一下,就很容易理解這個模塊是怎麼生成sql的
代碼出來了,咱們直接上單元測試跑一下看看效果吧
#!/usr/bin/evn python # coding=utf-8 import unittest from common.string_helper import string from logic import product_logic class DbHelperTest(unittest.TestCase): """數據庫操做包測試類""" def setUp(self): """初始化測試環境""" print('------ini------') def tearDown(self): """清理測試環境""" print('------clear------') def test(self): ############################################## # 只須要看這裏,其餘代碼是測試用例的模板代碼 # ############################################## # 實例化product表操做類ProductLogic _product_logic = product_logic.ProductLogic() # 測試編輯記錄 fields = { 'name': "'產品名稱'", 'content': "'產品詳情'", } result = _product_logic.edit(fields, 'id=2', 'product_class_id') print(result) ############################################## if __name__ == '__main__': unittest.main()
輸出結果:
------ini------ [{'id': 2, 'product_class_id': 1}] ------clear------
對於經過主鍵id修改記錄的操做,咱們也是最經常使用的,因此咱們能夠增長一個經過主鍵值來修改記錄的方法,能夠在寫參數時少寫一個參數
def edit_model(self, pk, fields, wheres='', returning=''): """編輯單條數據庫記錄""" if not pk: return {} elif wheres: wheres = self.__pk_name + ' = ' + str(id) + ' and ' + wheres else: wheres = self.__pk_name + ' = ' + str(id) return self.edit(fields, wheres, returning)
有些朋友可能會奇怪,這裏都知道主健了,爲何還要增長wheres條件呢?這是由於,咱們在更新一些記錄時,好比說更新訂單,咱們雖然知道訂單的主鍵值,但這個訂單並不必定就屬於這個用戶的,或者是該訂單指定狀態才能進行相關的操做,不然不能修改,這時咱們就能夠直接添加條件值來進行更新,若是條件不成立時則更新失敗
前面的接口咱們也改造一下
1 @put('/api/product/<id:int>/') 2 def callback(id): 3 """ 4 修改記錄 5 """ 6 name = web_helper.get_form('name', '產品名稱') 7 code = web_helper.get_form('code', '產品編碼') 8 product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '產品分類')) 9 standard = web_helper.get_form('standard', '產品規格') 10 quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保質期') 11 place_of_origin = web_helper.get_form('place_of_origin', '產地') 12 front_cover_img = web_helper.get_form('front_cover_img', '封面圖片') 13 content = web_helper.get_form('content', '產品描述', is_check_special_char=False) 14 # 防sql注入攻擊處理 15 content = string_helper.filter_str(content, "'") 16 # 防xss攻擊處理 17 content = string_helper.clear_xss(content) 18 is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否啓用')) 19 20 # 設置新增參數 21 fields = { 22 'name': string(name), 23 'code': string(code), 24 'product_class_id': product_class_id, 25 'standard': string(standard), 26 'quality_guarantee_period': string(quality_guarantee_period), 27 'place_of_origin': string(place_of_origin), 28 'front_cover_img': string(front_cover_img), 29 'content': string(content), 30 'is_enable': is_enable, 31 } 32 # 實例化product表操做類ProductLogic 33 _product_logic = product_logic.ProductLogic() 34 # 修改記錄 35 result = _product_logic.edit_model(id, fields) 36 # 判斷是否提交成功 37 if result: 38 return web_helper.return_msg(0, '成功') 39 else: 40 return web_helper.return_msg(-1, "提交失敗")
版權聲明:本文原創發表於 博客園,做者爲 AllEmpty 本文歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然視爲侵權。
python開發QQ羣:669058475(本羣已滿)、733466321(能夠加2羣) 做者博客:http://www.cnblogs.com/EmptyFS/