我的第一個python web開發框架(17)——產品管理


  這是后台管理系統最后一個功能,產品管理,它的接口與頁面功能與上一章差不多。

 

 

  獲取產品列表接口

 1 @get('/api/product/')
 2 def callback():
 3     """
 4     獲取列表數據
 5     """
 6     # 設置查詢條件
 7     wheres = ''
 8     # 產品分類id
 9     product_class_id = convert_helper.to_int0(web_helper.get_query('product_class_id', '', is_check_null=False))
10     if product_class_id > 0:
11         wheres = 'where product_class_id=' + str(product_class_id)
12     # 頁面索引
13     page_number = convert_helper.to_int1(web_helper.get_query('page', '', is_check_null=False))
14     # 頁面顯示記錄數量
15     page_size = convert_helper.to_int0(web_helper.get_query('rows', '', is_check_null=False))
16     # 排序字段
17     sidx = web_helper.get_query('sidx', '', is_check_null=False)
18     # 順序還是倒序排序
19     sord = web_helper.get_query('sord', '', is_check_null=False)
20     # 初始化排序字段
21     order_by = 'id desc'
22     if sidx:
23         order_by = sidx + ' ' + sord
24 
25     #############################################################
26     # 初始化輸出格式(前端使用jqgrid列表,需要指定輸出格式)
27     data = {
28         'records': 0,
29         'total': 0,
30         'page': 1,
31         'rows': [],
32     }
33     #############################################################
34     # 執行sql,獲取指定條件的記錄總數量
35     sql = 'select count(1) as records from product %(wheres)s' % {'wheres': wheres}
36     result = db_helper.read(sql)
37     # 如果查詢失敗或不存在指定條件記錄,則直接返回初始值
38     if not result or result[0]['records'] == 0:
39         return data
40     # 保存總記錄數量
41     data['records'] = result[0].get('records', 0)
42 
43     #############################################################
44     ### 設置分頁索引與頁面大小 ###
45     # 設置分頁大小
46     if page_size is None or page_size <= 0:
47         page_size = 10
48     # 計算總頁數
49     if data['records'] % page_size == 0:
50         page_total = data['records'] // page_size
51     else:
52         page_total = data['records'] // page_size + 1
53     # 記錄總頁面數量
54     data['total'] = page_total
55 
56     # 判斷提交的頁碼是否超出范圍
57     if page_number < 1 or page_number > page_total:
58         page_number = page_total
59     # 記錄當前頁面索引值
60     data['page'] = page_number
61 
62     # 計算當前頁面要顯示的記錄起始位置
63     record_number = (page_number - 1) * page_size
64     # 設置查詢分頁條件
65     paging = ' limit ' + str(page_size) + ' offset ' + str(record_number)
66     ### 設置排序 ###
67     if not order_by:
68         order_by = 'id desc'
69     #############################################################
70 
71     # 組合sql查詢語句
72     sql = "select * from product %(wheres)s order by %(orderby)s %(paging)s" % \
73            {'wheres': wheres, 'orderby': order_by, 'paging': paging}
74     # 讀取記錄
75     result = db_helper.read(sql)
76     if result:
77         # 存儲記錄
78         data['rows'] = result
79 
80     if data:
81         # 直接輸出json
82         return web_helper.return_raise(json.dumps(data, cls=json_helper.CJsonEncoder))
83     else:
84         return web_helper.return_msg(-1, "查詢失敗")
View Code

  這個接口多了按產品分類id查詢的條件,如果少了這個的話,直接將產品分類字段替換為產品字段變量就可以了。

  大家可以看到這里的代碼好像有點復雜。是的,這里要進行分頁查詢進行了分頁處理,所以代碼有點多,不過寫了很詳細的注釋,只要你對python的基本語法、字典的處理理解,然后對之前工具函數那里按要求重寫過測試用例,那么對閱讀這段代碼是沒有什么大問題的。

  下面再重新幫大家熟悉一下前面講述過的工具函數

product_class_id = convert_helper.to_int0(web_helper.get_query('product_class_id', '產品分類id', is_check_null=False))

  這是獲取客戶端(HTML)用AJAX提交上來的產品分類id接收處理,如果你認真看過前面工具函數內容的話,看到web_helper.get_query()這個函數應該會很熟悉,它就是獲取GET方式提交值的接收函數,第一個參數是要接收的變量名稱,第二個參數是這個變量的中文說明,第三個是在接收參數時,是否做非空判斷,當前設置為這不是必填項。默認它為True,當為True時,如果客戶端沒有提交這個參數值,則系統自動會返回“xxx 不允許為空”,這個xxx就是第二個參數,也就是當前變量的中文說明,還有其他參數大家可以打看web_helper.py查看。

  convert_helper.to_int0()這個函數,在前面工具函數第一篇中講到的函數,它會將接收到的參數字符串轉為int類型值,如果這個參數小於0時,會自動使用默認值0代替。

 

sql = 'select count(1) as records from product %(wheres)s' % {'wheres': wheres}

  使用習慣ORM的朋友可能會不太習慣直接寫sql語句,本系列第一部分主要面向沒有什么基礎的朋友,所以盡量不封裝各種類和函數,這樣大家直接看到內容會更容易理解。第二部分會教大家自己簡單封裝一個ORM,到時重構后重復代碼就會減少一大半。

  上面這行是獲取當前查詢有多少條記錄的sql語句,熟悉python字符串替換的朋友應該會很熟悉,它會將字符串%后面的字典內容替代字符串中對應的鍵值,如果wheres值為空時,則替換空值,即將%(wheres)s這個鍵值替換掉。

  python的字符串替換有多種方式,而這里使用字典方式來替換會讓代碼可讀性更高,而且字典中各個值的位置不需要按固定方式擺放,不容易出錯。

 

  獲取指定id的記錄實體

 1 @get('/api/product/<id:int>/')
 2 def callback(id):
 3     """
 4     獲取指定記錄
 5     """
 6     sql = """select * from product where id = %s""" % (id,)
 7     # 讀取記錄
 8     result = db_helper.read(sql)
 9     if result:
10         # 直接輸出json
11         return web_helper.return_msg(0, '成功', result[0])
12     else:
13         return web_helper.return_msg(-1, "查詢失敗")

  這段代碼比較簡單,第6行使用的就是%s替換字符串方式,后面的元組(id,)  好像python3以后元組里不加逗號替換也沒有問題,python2是一定要加的。

 

  添加產品與修改產品接口

 1 @post('/api/product/')
 2 def callback():
 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     # 添加記錄(使用returning這個函數能返回指定的字段值,這里要求返回新添加記錄的自增id值)
21     sql = """insert into product (name, code, product_class_id, standard, quality_guarantee_period,
22                 place_of_origin, front_cover_img, content, is_enable)
23               values (%s, %s, %s, %s, %s, %s, %s, %s, %s) returning id"""
24     vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content, is_enable)
25     # 寫入數據庫
26     result = db_helper.write(sql, vars)
27     # 判斷是否提交成功
28     if result and result[0].get('id'):
29         return web_helper.return_msg(0, '成功')
30     else:
31         return web_helper.return_msg(-1, "提交失敗")
32 
33 
34 @put('/api/product/<id:int>/')
35 def callback(id):
36     """
37     修改記錄
38     """
39 
40     name = web_helper.get_form('name', '產品名稱')
41     code = web_helper.get_form('code', '產品編碼')
42     product_class_id = convert_helper.to_int0(web_helper.get_form('product_class_id', '產品分類'))
43     standard = web_helper.get_form('standard', '產品規格')
44     quality_guarantee_period = web_helper.get_form('quality_guarantee_period', '保質期')
45     place_of_origin = web_helper.get_form('place_of_origin', '產地')
46     front_cover_img = web_helper.get_form('front_cover_img', '封面圖片')
47     content = web_helper.get_form('content', '產品描述', is_check_special_char=False)
48     # 防sql注入攻擊處理
49     content = string_helper.filter_str(content, "'")
50     # 防xss攻擊處理
51     content = string_helper.clear_xss(content)
52     is_enable = convert_helper.to_int0(web_helper.get_form('is_enable', '是否啟用'))
53 
54     # 編輯記錄
55     sql = """
56           update product
57             set name=%s, code=%s, product_class_id=%s, standard=%s, quality_guarantee_period=%s,
58                 place_of_origin=%s, front_cover_img=%s, content=%s, is_enable=%s
59           where id=%s returning id"""
60     vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content,
61             is_enable, id)
62     # 寫入數據庫
63     result = db_helper.write(sql, vars)
64     # 判斷是否提交成功
65     if result and result[0].get('id'):
66         return web_helper.return_msg(0, '成功')
67     else:
68         return web_helper.return_msg(-1, "提交失敗")
View Code

  使用非get方式提交時,即使用post、put、delete等方式提交參數時,需要使用web_helper.get_form()函數來接收,這一點大家要注意,不然就會獲取不到客戶端提交的參數值

    # 添加記錄(使用returning這個函數能返回指定的字段值,這里要求返回新添加記錄的自增id值)
    sql = """insert into product (name, code, product_class_id, standard, quality_guarantee_period,
                place_of_origin, front_cover_img, content, is_enable)
              values (%s, %s, %s, %s, %s, %s, %s, %s, %s) returning id"""
    vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content, is_enable)
    # 寫入數據庫
    result = db_helper.write(sql, vars)

  新增記錄時,容易出錯的地方是參數中的%s與字段數量不匹配,這里大家要注意一下。另外,在insert語句的后尾最好加上returning id或returning *  返回新增記錄值或整個記錄實體,方便用來判斷是否插入成功,如果返回這些內容的話,比較難判斷數據庫記錄是否添加成功了

    # 編輯記錄
    sql = """
          update product
            set name=%s, code=%s, product_class_id=%s, standard=%s, quality_guarantee_period=%s,
                place_of_origin=%s, front_cover_img=%s, content=%s, is_enable=%s
          where id=%s returning id"""
    vars = (name, code, product_class_id, standard, quality_guarantee_period, place_of_origin, front_cover_img, content,
            is_enable, id)
    # 寫入數據庫
    result = db_helper.write(sql, vars)

  更新記錄時,參數元組中記錄要將記錄的id值放進來,不然也會出現sql執行異常的問題,這個也是容易出錯的地方。

 

  刪除記錄接口

 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, "刪除失敗")

  

  前端代碼大家自己可以比較一下上一章,看看有什么不同

  非常感謝Sunshine-X 的提醒,在產品編輯頁面的js中,添加了保存成功后jqgrid表格刷新代碼(本人前端比較菜)

  后面附上完整的項目代碼

 

 

  本文對應的源碼下載

 

版權聲明:本文原創發表於 博客園,作者為 AllEmpty 本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。

python開發QQ群:669058475(本群已滿)、733466321(可以加2群)    作者博客:http://www.cnblogs.com/EmptyFS/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM