Django的資料模型層實現特點

2022-07-04 04:30:16 字數 2089 閱讀 1313

我在資料層的抽象上走了一段比較長的彎路。簡單總結一下:

剛開始做簡單的專案時,用簡單的activerecord就已經很合適了,比如codeigniter自帶的。但是專案變大之後,特別是業務實體之間的關聯變多之後馬上就出現了問題,為了降低各個實體間的耦合,你需要將各種操作再抽象出一層。舉個例子:你做了乙個簡單的使用者系統,對使用者的增刪改查只需要對「使用者類」呼叫相應的操作就行了。後來你增加了乙個檔案類,每個使用者可以擁有多個檔案,刪除使用者時需要同時刪除相應的檔案。為了能使刪除的使用者的這個操作復用,同時防止其他操作刪除使用者時沒有刪除相應資料夾,於是你不得不再對使用者的刪除做一層封裝。我曾經試圖讓各種實體在構建的時候就說明與其他實體的關係,這樣寫業務邏輯的時候就能盡量少的受打擾。後來發現這也是錯誤的,因為把關係寫到資料層以後,遇到特殊的邏輯就很難操作了。還是剛才那個例子:如果有一天我增加了乙個分享功能,同時規定刪除使用者時不刪除他已經分享的檔案,這時該怎麼辦?當然有些其他繞的方法可以實現,比如分享檔案的時候就複製檔案到另乙個特殊的使用者賬戶下,使用者讀取的分享檔案其實都是這個特殊使用者賬戶的。但是系統大了之後,這種特殊方法就會多得煩人。後來在我寫climbphp時,才算是找到了乙個較為合理的方法。就是系統應該以具體的業務邏輯來分模組,資料實體是從屬於業務邏輯模組的。模組間的聯絡是通過丟擲和監聽事件實現的。資料實體之間不再有直接的關聯。還是以剛才的背景來舉例子:系統分為使用者、檔案、分享三個模組,使用者模組接受正常的刪除指令,成功後向外丟擲事件。檔案模組監聽使用者刪除事件,同時刪除相應的檔案。分享模組也監聽使用者刪除事件,監聽到之後獲取使用者除了分享出去的檔案以外可刪除的檔案,然後阻斷原來的使用者刪除事件,改為丟擲可刪除檔案的事件。這樣的好處在於,每乙個模組開發完成之後都可以完全封閉。當系統關閉共享模組時,原有系統不需要任何改動,仍然可用。不過這樣做的前提在於需要有乙個足夠強大的事件派發中心。參見climbphp。

對orm我沒有用到過真正的專案中,一是因為有些業務邏輯太複雜,調研的orm都不能滿足效能上的需求。二是因為語法太難看,不想用。學django的時候發現django的資料模型層很成熟,具體特點記錄如下:

這一部分應該是最影響資料庫效能的。django在查詢有關聯實體的實體時,預設時先查詢主實體,然後根據關聯項依次查詢對關聯實體。如果你查詢的主實體是多個,那麼會依次對每乙個再去資料庫查詢相關聯的實體。為了優化,django提供了乙個prefetch_related方法,能一次性查詢所有相關聯的實體,然後通過python組裝。對於一對一的關聯,django還提供了selecte_related方法,這個方法使用的join來查詢。

除了在查詢方法上加速,django還支援「關聯物件」的延遲載入,也就是當訪問關聯的物件時才再次訪問資料庫。這一點我特別注意了一下,因為最近讀了csdn范凱的關於orm的總結,他說實際專案中資料庫的瓶頸在於io而不是併發。將複雜的查詢拆分成簡單的資料庫查詢可以極大地提高快取利用率,降低磁碟io。但是django延遲載入關聯實體在實際情況下效能如何我沒有考證過。

這裡值得注意的是,django在實現資料模型層的時候應該是用到了python語言本身擴充套件自己語法的特性。因為它直接使用了python的切片語法來實現sql的limit操作。如 users.objects.all()[0:5],在django文件中說明了all()操作會造成資料庫訪問,如果沒有對語法進行擴充套件的話,那麼切片時豈不是已經對資料庫進行了全表查詢?

對普通的資料查詢來說,djang沒有提供特別的快取方式,需要使用者手工用變數來快取上次查詢的結果。對於關聯資料,如果執行了select_related()或者prefetch_related(),那麼通過self來讀取關聯實體時讀取的是快取。

django提供了三種繼承方式,php的doctrine也實現了類似的方式。三種繼承分別是:「繼承自抽象父類」,「繼承自普通資料模型」,「繼承變成**」。具體意義分別是:「抽象父類只包括通用屬性或者方法,本身不能生成表」;「繼承後的模型對自己的特有字段生成新錶」;「繼承後的模型不生成新錶,只是乙個可以複寫源模型行為的**」。

總結:1.關於orm感覺已經沒有太多值得討論的了,請看csdn范凱的 《web的快取設計模式》。

2.資料層以及持久化的具體實現其實不需要糾結,目前的orm已經足夠強大,真正糾結的是業務邏輯造成的資料模型關聯。也是我開篇一堆廢話所說的。

4.nosql將如何改變框架中的資料模型層?我認為沒有太大改變,如上所說,資料庫如何變化說到底只是資料如何持久化。框架始終關注的是如何更好的表現業務邏輯。

Django 資料模型高階

訪問外來鍵 foreignkey 值 當你訪問乙個外來鍵屬性時,獲取的是乙個資料模型物件 models.py from django.db import models class publisher models.model name models.charfield max length 50 w...

Django 資料模型欄位及屬性

autofield 乙個能夠根據可用id自增的 integerfield booleanfield 乙個真 假 true false 字段 charfield max length 乙個字串字段,適用於中小長度的字串。對於長段的文字,請使用 textfield commaseparatedinteg...

django資料模型中關於on delete的使用

class bookmodel models.model 書籍表 book name models.charfield max length 100,verbose name 書名 表示外來鍵關聯到作者表,當作者表刪除了該條資料,圖書表中不刪除,僅僅是把外來鍵置空 author models.for...