Django源代碼閱讀分析-2:持久層結構分析

聲明:本文爲轉載

      Django對持久層的封裝得很好,很好地支持Mysql、PostgreSQL、Oracle、SQLite3等流行的關係型數據庫。頂層提供統一的模型封裝,使用者基本無須關心真實數據庫底層的細節,甚至對DBMS本身知之甚少也沒關係。

      Django做到這點的的方法之一是進行了抽象和封裝。不再對外暴露SQL語句本身,甚至連具體DBMS也以統一的界面爲使用者做了隔離,用戶看到的只有同一的Model模型,或者一些命令行Command,這些Model或Command與實際DBMS的溝通,都被封裝到了經過高度抽象的Backend模塊中。如下圖所示爲Django持久層模型概覽:

 

        Django對持久層的封裝的python模塊寫在Django.Db.Backends包中,其下的每一個包對應一種具體的數據庫類型,上面所提到的MySQL、SQLite等就是以包的形式存在於Django.Db.Backends下的。以MySQL爲例我整理了一下其類層次結構。畫類圖的過程中發現,對python的建模和Java不同,因爲python中一個模塊中可以有多個類結構,還可以有一些面向過程的語句。而Java中一般都是一個文件一個類(當然,內部類除外),建模的時候很容易使用類圖表達。

        基於“抽象”的思維,Django爲它所支持的底層數據庫類型提供了一致的接口,但這個接口並非其下所有接口的共有操作,而是提供了底下所有操作的一個超集。例如,對於DatabasseOperations類的方法,在SQLite3中有convert_values()方法,在Mysql的操作中是沒有此方法的;但在Mysql中又有value_to_db_datetime()和value_to_db_time()等SQLite3所沒有的操作。而這些操作在其父類BaseDatabaseOperations中都有。

        以MySQL爲例,畫了Backends內部類圖之間的關係,細節如下圖所示,其實對於其他的數據庫實現的支持,也是差不多的。

 

        模型最原始的調用在最頂層的__init__.py中。load_backends()方法會根據settings.py中的配置項import對應的DB驅動和backend模塊。有一個比較巧而且也算典型的python代碼寫法,在db.__init__.py的load_backend(backend_name)函數中:

        改語句是出現導入backend異常的時候出現的,當然後不被支持的數據庫後端時,系統找不到對應的backend實例,就會拋出異常,同時會把目前已被支持的數據庫列舉一遍,列舉是通過掃描Django/Db/Backends目錄下的文件完成的(前面說過,每一種實際被支持的數據庫後端,都必須在Backends目錄下建立子目錄然後在其中繼承實現第二幅圖中藍色的幾個基類),如果該文件f是一個子目錄,並且目錄名不是"."開頭的,則把這些目錄名合併成一個列表返回賦值給available_backends變量。這是一個完整語句所完成的功能,相比於Java代碼,十分簡潔。

available_backends = [f for f in os.listdir(backend_dir) \ 
        if os.path.isdir(os.path.join(backend_dir, f))  \ 
        and not f.startswith('.')]

        至於更細節的數據庫封裝實現,可以以MySQL爲例參考Django源代碼,源代碼樹的位置是Django/Db/Backends/Mysql。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章