我的第一個python web開發框架(30)——定製ORM(七)

来源:https://www.cnblogs.com/EmptyFS/archive/2018/08/16/9484680.html
-Advertisement-
Play Games

幾個複雜的ORM方式都已介紹完了,剩下一些常用的刪除、獲取記錄數量、統計合計數、獲取最大值、獲取最小值等方法我就不一一詳細介紹了,直接給出代碼大家自行查看。 1 #!/usr/bin/env python 2 # coding=utf-8 3 4 from common import db_help ...


  幾個複雜的ORM方式都已介紹完了,剩下一些常用的刪除、獲取記錄數量、統計合計數、獲取最大值、獲取最小值等方法我就不一一詳細介紹了,直接給出代碼大家自行查看。

  1 #!/usr/bin/env python
  2 # coding=utf-8
  3 
  4 from common import db_helper
  5 
  6 
  7 class LogicBase():
  8     """邏輯層基礎類"""
  9 
 10     def __init__(self, db, is_output_sql, table_name, column_name_list='*', pk_name='id'):
 11         """類初始化"""
 12         # 資料庫參數
 13         self.__db = db
 14         # 是否輸出執行的Sql語句到日誌中
 15         self.__is_output_sql = is_output_sql
 16         # 表名稱
 17         self.__table_name = str(table_name).lower()
 18         # 查詢的列欄位名稱,*表示查詢全部欄位,多於1個欄位時用逗號進行分隔,除了欄位名外,也可以是表達式
 19         self.__column_name_list = str(column_name_list).lower()
 20         # 主健名稱
 21         self.__pk_name = str(pk_name).lower()
 22 
 23     #####################################################################
 24     ### 執行Sql ###
 25 
 26     def select(self, sql):
 27         """執行sql查詢語句(select)"""
 28         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
 29             # 執行sql語句
 30             result = db.execute(sql)
 31             if not result:
 32                 result = []
 33         return result
 34 
 35     def execute(self, sql):
 36         """執行sql語句,並提交事務"""
 37         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
 38             # 執行sql語句
 39             result = db.execute(sql)
 40             if result:
 41                 db.commit()
 42             else:
 43                 result = []
 44         return result
 45 
 46     def copy(self, values, columns):
 47         """批量更新數據"""
 48         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
 49             # 執行sql語句
 50             result = db.copy(values, self.__table_name, columns)
 51         return result
 52 
 53     def get_model(self, wheres):
 54         """通過條件獲取一條記錄"""
 55         # 如果有條件,則自動添加where
 56         if wheres:
 57             wheres = ' where ' + wheres
 58 
 59         # 合成sql語句
 60         sql = "select %(column_name_list)s from %(table_name)s %(wheres)s" % \
 61               {'column_name_list': self.__column_name_list, 'table_name': self.__table_name, 'wheres': wheres}
 62         # 初化化資料庫鏈接
 63         result = self.select(sql)
 64         if result:
 65             return result[0]
 66         return {}
 67 
 68     def get_model_for_pk(self, pk, wheres=''):
 69         """通過主鍵值獲取資料庫記錄實體"""
 70         if not pk:
 71             return {}
 72         # 組裝查詢條件
 73         wheres = '%s = %s' % (self.__pk_name, str(pk))
 74 
 75         return self.get_model(wheres)
 76 
 77     def get_value(self, column_name, wheres=''):
 78         """
 79         獲取指定條件的欄位值————多於條記錄時,只取第一條記錄
 80         :param column_name: 單個欄位名,如:id
 81         :param wheres: 查詢條件
 82         :return: 7 (指定的欄位值)
 83         """
 84         if not column_name:
 85             return None
 86         elif wheres:
 87             wheres = ' where ' + wheres
 88 
 89         sql = 'select %(column_name)s from %(table_name)s %(wheres)s limit 1' % \
 90               {'column_name': column_name, 'table_name': self.__table_name, 'wheres': wheres}
 91         result = self.select(sql)
 92         # 如果查詢成功,則直接返回記錄字典
 93         if result:
 94             return result[0].get(column_name)
 95 
 96     def get_value_list(self, column_name, wheres=''):
 97         """
 98         獲取指定條件記錄的欄位值列表
 99         :param column_name: 單個欄位名,如:id
100         :param wheres: 查詢條件
101         :return: [1,3,4,6,7]
102         """
103         if not column_name:
104             column_name = self.__pk_name
105         elif wheres:
106             wheres = ' where ' + wheres
107 
108         sql = 'select array_agg(%(column_name)s) as list from %(table_name)s %(wheres)s' % \
109               {'column_name': column_name, 'table_name': self.__table_name, 'wheres': wheres}
110         result = self.select(sql)
111         # 如果查詢失敗或不存在指定條件記錄,則直接返回初始值
112         if result and isinstance(result, list):
113             return result[0].get('list')
114         else:
115             return []
116 
117     def add_model(self, fields, returning=''):
118         """新增資料庫記錄"""
119         ### 拼接sql語句 ###
120         # 初始化變數
121         key_list = []
122         value_list = []
123         # 將傳入的字典參數進行處理,把欄位名生成sql插入欄位名數組和字典替換數組
124         # PS:字元串使用字典替換參數時,格式是%(name)s,這裡會生成對應的字串
125         # 比如:
126         #   傳入的字典為: {'id': 1, 'name': '名稱'}
127         #   那麼生成的key_list為:'id','name'
128         #   而value_list為:'%(id)s,%(name)s'
129         #   最終而value_list為字元串對應名稱位置會被替換成相應的值
130         for key in fields.keys():
131             key_list.append(key)
132             value_list.append('%(' + key + ')s')
133         # 設置sql拼接字典,並將數組(lit)使用join方式進行拼接,生成用逗號分隔的字元串
134         parameter = {
135             'table_name': self.__table_name,
136             'pk_name': self.__pk_name,
137             'key_list': ','.join(key_list),
138             'value_list': ','.join(value_list)
139         }
140         # 如果有指定返回參數,則添加
141         if returning:
142             parameter['returning'] = ', ' + returning
143         else:
144             parameter['returning'] = ''
145 
146         # 生成可以使用字典替換的字元串
147         sql = "insert into %(table_name)s (%(key_list)s) values (%(value_list)s) returning %(pk_name)s %(returning)s" % parameter
148         # 將生成好的字元串替字典參數值,生成最終可執行的sql語句
149         sql = sql % fields
150 
151         result = self.execute(sql)
152         if result:
153             return result[0]
154         return {}
155 
156     def edit(self, fields, wheres='', returning=''):
157         """批量編輯資料庫記錄"""
158         ### 拼接sql語句 ###
159         # 拼接欄位與值
160         field_list = [key + ' = %(' + key + ')s' for key in fields.keys()]
161         # 設置sql拼接字典
162         parameter = {
163             'table_name': self.__table_name,
164             'pk_name': self.__pk_name,
165             'field_list': ','.join(field_list)
166         }
167         # 如果存在更新條件,則將條件添加到sql拼接更換字典中
168         if wheres:
169             parameter['wheres'] = ' where ' + wheres
170         else:
171             parameter['wheres'] = ''
172 
173         # 如果有指定返回參數,則添加
174         if returning:
175             parameter['returning'] = ', ' + returning
176         else:
177             parameter['returning'] = ''
178 
179         # 生成sql語句
180         sql = "update %(table_name)s set %(field_list)s %(wheres)s returning %(pk_name)s %(returning)s" % parameter
181         sql = sql % fields
182 
183         return self.execute(sql)
184 
185     def edit_model(self, pk, fields, wheres='', returning=''):
186         """編輯單條資料庫記錄"""
187         if not pk:
188             return {}
189         elif wheres:
190             wheres = self.__pk_name + ' = ' + str(pk) + ' and ' + wheres
191         else:
192             wheres = self.__pk_name + ' = ' + str(pk)
193 
194         return self.edit(fields, wheres, returning)
195 
196     def delete(self, wheres='', returning='', is_update_cache=True):
197         """批量刪除資料庫記錄"""
198         # 如果存在條件
199         if wheres:
200             wheres = ' where ' + wheres
201 
202         # 如果有指定返回參數,則添加
203         if returning:
204             returning = ', ' + returning
205 
206         # 生成sql語句
207         sql = "delete from %(table_name)s %(wheres)s returning %(pk_name)s %(returning)s" % \
208               {'table_name': self.__table_name, 'wheres': wheres, 'pk_name': self.__pk_name, 'returning': returning}
209         return self.execute(sql)
210 
211     def delete_model(self, pk, wheres='', returning='', is_update_cache=True):
212         """刪除單條資料庫記錄"""
213         if not pk:
214             return {}
215         elif wheres:
216             wheres = self.__pk_name + ' = ' + str(pk) + ' and ' + wheres
217         else:
218             wheres = self.__pk_name + ' = ' + str(pk)
219 
220         return self.delete(wheres, returning)
221 
222     def get_list(self, column_name_list='', wheres='', page_number=None, page_size=None, orderby=None, table_name=None):
223         """
224         獲取指定條件的資料庫記錄集
225         :param column_name_list:      查詢欄位
226         :param wheres:      查詢條件
227         :param page_number:   分頁索引值
228         :param page_size:    分頁大小, 存在值時才會執行分頁
229         :param orderby:     排序規則
230         :param table_name:     查詢數據表,多表查詢時需要設置
231         :return: 返回記錄集總數量與分頁記錄集
232             {'records': 0, 'total': 0, 'page': 0, 'rows': []}
233         """
234         # 初始化輸出參數:總記錄數量與列表集
235         data = {
236             'records': 0,  # 總記錄數
237             'total': 0,  # 總頁數
238             'page': 1,  # 當前頁面索引
239             'rows': [],  # 查詢結果(記錄列表)
240         }
241         # 初始化查詢數據表名稱
242         if not table_name:
243             table_name = self.__table_name
244         # 初始化查詢欄位名
245         if not column_name_list:
246             column_name_list = self.__column_name_list
247         # 初始化查詢條件
248         if wheres:
249             # 如果是字元串,表示該查詢條件已組裝好了,直接可以使用
250             if isinstance(wheres, str):
251                 wheres = 'where ' + wheres
252             # 如果是list,則表示查詢條件有多個,可以使用join將它們用and方式組合起來使用
253             elif isinstance(wheres, list):
254                 wheres = 'where ' + ' and '.join(wheres)
255         # 初始化排序
256         if not orderby:
257             orderby = self.__pk_name + ' desc'
258         # 初始化分頁查詢的記錄區間
259         paging = ''
260 
261         with db_helper.PgHelper(self.__db, self.__is_output_sql) as db:
262             #############################################################
263             # 判斷是否需要進行分頁
264             if not page_size is None:
265                 ### 執行sql,獲取指定條件的記錄總數量
266                 sql = 'select count(1) as records from %(table_name)s %(wheres)s ' % \
267                       {'table_name': table_name, 'wheres': wheres}
268                 result = db.execute(sql)
269                 # 如果查詢失敗或不存在指定條件記錄,則直接返回初始值
270                 if not result or result[0]['records'] == 0:
271                     return data
272 
273                 # 設置記錄總數量
274                 data['records'] = result[0].get('records')
275 
276                 #########################################################
277                 ### 設置分頁索引與頁面大小 ###
278                 if page_size <= 0:
279                     page_size = 10
280                 # 計算總分頁數量:通過總記錄數除於每頁顯示數量來計算總分頁數量
281                 if data['records'] % page_size == 0:
282                     page_total = data['records'] // page_size
283                 else:
284                     page_total = data['records'] // page_size + 1
285                 # 判斷頁碼是否超出限制,超出限制查詢時會出現異常,所以將頁面索引設置為最後一頁
286                 if page_number < 1 or page_number > page_total:
287                     page_number = page_total
288                 # 記錄總頁面數量
289                 data['total'] = page_total
290                 # 記錄當前頁面值
291                 data['page'] = page_number
292                 # 計算當前頁面要顯示的記錄起始位置(limit指定的位置)
293                 record_number = (page_number - 1) * page_size
294                 # 設置查詢分頁條件
295                 paging = ' limit ' + str(page_size) + ' offset ' + str(record_number)
296             #############################################################
297 
298             ### 按條件查詢資料庫記錄
299             sql = "select %(column_name_list)s from %(table_name)s %(wheres)s order by %(orderby)s %(paging)s" % \
300                   {'column_name_list': column_name_list,
301                    'table_name': table_name,
302                    'wheres': wheres,
303                    'orderby': orderby,
304                    'paging': paging}
305             result = db.execute(sql)
306             if result:
307                 data['rows'] = result
308                 # 不需要分頁查詢時,直接在這裡設置總記錄數
309                 if page_size is None:
310                     data['records'] = len(result)
311 
312         return data
313 
314     def get_count(self, wheres=''):
315         """獲取指定條件記錄數量"""
316         if wheres:
317             wheres = ' where ' + wheres
318         sql = 'select count(1) as total from %(table_name)s %(wheres)s ' % \
319               {'table_name': self.__table_name, 'wheres': wheres}
320         result = self.select(sql)
321         # 如果查詢存在記錄,則返回true
322         if result:
323             return result[0].get('total')
324         return 0
325 
326     def get_sum(self, fields, wheres):
327         """獲取指定條件記錄數量"""
328         sql = 'select sum(%(fields)s) as total from %(table_name)s where %(wheres)s ' % \
329               {'table_name': self.__table_name, 'wheres': wheres, 'fields': fields}
330         result = self.select(sql)
331         # 如果查詢存在記錄,則返回true
332         if result and result[0].get('total'):
333             return result[0].get('total')
334         return 0
335 
336     def get_min(self, fields, wheres):
337         """獲取該列記錄最小值"""
338         sql = 'select min(%(fields)s) as min from %(table_name)s where %(wheres)s ' % \
339               {'table_name': self.__table_name, 'wheres': wheres, 'fields': fields}
340         result = self.select(sql)
341         # 如果查詢存在記錄,則返回true
342         if result and result[0].get('min'):
343             return result[0].get('min')
344 
345     def get_max(self, fields, wheres):
346         """獲取該列記錄最大值"""
347         sql = 'select max(%(fields)s) as max from %(table_name)s where %(wheres)s ' % \
348               {'table_name': self.__table_name, 'wheres': wheres, 'fields': fields}
349         result = self.select(sql)
350         # 如果查詢存在記錄,則返回true
351         if result and result[0].get('max'):
352             return result[0].get('max')
353 
354             #####################################################################
View Code

 

  大家只要掌握了ORM簡單的組合sql方法,就可以自由發揮,根據自己的需要去創建不同的方法了,也可以隨意更換mysql、mssql等資料庫。

  當然,這隻是最簡單的ORM方式,提交欄位參數和條件參數時,它不會自動分辨欄位的類型,不會自動初始化預設值,如果想讓它變的更加強大,還需要做更多的改造與處理,這樣做的話它也會跟著變的更加複雜和難懂,性能也會跟著下降。不過當前功能對於多數項目來說,已經足夠使用了。大家如果有需要可以自行研究進行擴展。

 

  在日常操作中,獲取指定記錄實體是最常見使用最頻繁的操作,為了減少對資料庫的查詢,我們可以將ORM與Nosql結合起來,提升ORM的操作性能,當然如果你不想使用nosql緩存,也可以直接跳過本章節。

  使用Nosql,首先我們需要一個鏈接Nosql的配置文件,用它來存儲Nosql的服務地址、埠、密碼等參數

  在config文件夾中我們創建redis_config.py配置文件

#!/usr/bin/env python
#	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • c/c++賦值函數(重載=號運算符) 首先c++里的各種運算符都是用函數實現的,比如=,就等號函數。 所以當用=給一個對象賦值的時候,實際調用的是=號所對應的=號函數。 分析下麵的代碼 c++ include using namespace std; class Test{ public: expl ...
  • 之前的一篇博客里我寫了關於在一個類中的程式初始化順序,但是在Java的面向對象里,類之間還存在著繼承的關係。所以關於程式的初始化順序,我們可以再細劃分為:父類靜態變數,父類的靜態代碼塊,父類構造器,父類非靜態變數,父類非靜態代碼塊,子類靜態變數,子類靜態代碼塊,子類構造器,子類非靜態成員變數和子類非 ...
  • c/c++拷貝構造函數和關鍵字explicit 關鍵字explicit 修飾構造方法的關鍵字,加上了,就告訴編譯器,不可以隱式初始化對象;不加就可以隱式初始化對象; 下麵的代碼是可以正常編譯執行的,但是加了關鍵字explicit,編譯就會錯我,因為Test t = 100;是隱式初始化對象,但是如果 ...
  • 給定一個大小為 n 的數組,找到其中的眾數。眾數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。 你可以假設數組是非空的,並且給定的數組總是存在眾數。 示例 1: 輸入: [3,2,3] 輸出: 3 示例 2: 輸入: [2,2,1,1,1,2,2] 輸出: 2 class Solution(ob ...
  • 給定一個正整數,返回它在 Excel 表中相對應的列名稱。 例如, 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -> AA 28 -> AB ... 示例 1: 輸入: 1 輸出: "A" 示例 2: 輸入: 28 輸出: "AB" 示例 3: 輸入: 701 輸出: " ...
  • $array[$j]){ $temp = $array[$i]; $array[$i] = $array[$j]; $array[$j] = $temp; } } } return $ar... ...
  • 給定一個已按照升序排列 的有序數組,找到兩個數使得它們相加之和等於目標數。 函數應該返回這兩個下標值index1 和 index2,其中 index1 必須小於 index2。 說明: 返回的下標值(index1 和 index2)不是從零開始的。 你可以假設每個輸入只對應唯一的答案,而且你不可以重 ...
  • 很多項目中都會遇到需要定時任務的情況,本篇文章就結合了Spring中以及SpringBoot、SpringCloud中定時任務的解決方案。 在Spring中使用定時器 用SpringBoot比較多的同學可能都會覺得Spring的xml配置確實比較麻煩,如果想在Spring中使用定時器的話其實是必須使 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...