我的第一個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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...