Django專案該如何佈局?我推薦這樣做

Janzou發表於2015-04-08

“Django應用、配置檔案以及其他各種相關目錄的最佳佈局是什麼樣的?”

總是有朋友問我們這個問題,因此我想花一點時間,寫一下我們究竟是如何看待這個問題的,這樣我們就可以很容易讓其他人蔘照這個文件。請注意,這裡是基於 Django 1.7.1 版寫的,但是可以很容易應用在 Django 1.4 版之後任何版本。

雖然 Django 1.4 釋出時,它包含了一個改進後的專案佈局(這還用了很長一段時間),但本文有一些優化專案佈局的更好建議。

為什麼這種佈局比較好

我們在這裡推薦的專案佈局有幾個優點,即:

  • 讓你獲得、重新打包並複用單個的Django應用來用於其他的專案。這通常是不明確的,正如你正在構建一個不管是否要複用的應用。在一開始以想要複用的方式構建應用,會讓這一切變得更加簡單。
  • 鼓勵設計可複用的應用。
  • 環境的詳細設定。在一個單一的整體配置檔案中,if DEBUG==True 沒有什麼意義。這使得很容易能看到哪些配置是共享的,哪些是在每個環境的基礎上可覆寫的。
  • 環境的具體安裝要求(PIP requirements)。
  • 如果有必要,專案級的模板和靜態檔案可以覆寫應用級的預設值。
  • 小而更具體的測試檔案更易於閱讀和理解。

假設你有兩個應用 blog users,以及兩個開發環境 dev 和 prod。你的專案佈局結構應該是這樣的:

本文的剩餘部分介紹瞭如何將專案遷移到這個佈局,以及為什麼這種佈局比較好。

當前預設佈局

我們將呼叫示例專案foo,我知道這是一個非常有創意的名字。我們假設在這裡,我們將要啟動foo.com。但當我們希望將我們的專案名稱對映最終域名時,該專案將以不以任何意義要求的方式存在在這裡。

如果你使用 django-admin.py startproject foo 命令開啟這個專案,你會得到一個像這樣的目錄結構:

這種佈局是一個好起點,我們有一個頂級目錄foo,裡面包含了manage.py檔案和專案目錄foo/foo/。在這個目錄,你可以查詢到原始碼控制系統(比如 Git) 。

你應該想到子目錄foo/foo/就是這個專案。這裡的所有檔案,不是一個Django應用程式,就是與專案相關的配套檔案。

修改配置

這裡的任務是修正不好的配置檔案。我將這個佈局向新使用者展示,我往往驚訝於這幾個人怎麼知道這甚至可能做到。事實上,當大家都知道這些配置只是Python程式碼時,他們也不將它們當做Python程式碼。

因此,讓我們來改進配置。對於oo專案而言,將有4個開發環境:dev、stage、jenkins 和 production。給每個開發環境一個它們自己的配置檔案。這個過程中要做的事情是:

  1. foo/foo/目錄下新建一個配置目錄,並在裡面建立一個空的__init __.py檔案。
  2. foo/foo/settings.py移動並重新命名為foo/foo/settings/base.py
  3. foo/foo/settings/目錄下建立單獨的dev.py、stage.py、jenkins.py production.py檔案。這四種環境的特定配置檔案應該包含如下內容:

為什麼這很重要呢?對於本地開發你想要設定DEBUG=True,但很容易不小心將這個推到生產程式碼中,因此需要開啟 foo/foo/settings/production.py 檔案,在初始匯入base後加上DEBUG=False。現在,對於這種愚蠢的錯誤,你的生產環境是安全的。

還有什麼可以定製?很明顯你可以針對不同的資料庫,甚至是不同的主機來配置staging、jenkins和production等開發環境。然後在每個環境配置檔案中來調整那些配置。

使用這些配置

無論你通常使用哪種方法,使用這些配置都非常簡單。要使用該作業系統的環境,你只要做:

現在你就在使用 jenkins 的配置。

或者,也許你更喜歡把它們作為這樣的命令列選項:

同樣的,如果你使用 gunicorn,命令則如下:

還有什麼可自定義的配置?

另一個實用建議是將一些預設的集合配置從元組改為列表。例如 INSTALLED_APPS,將它從:

改為:

現在,基於每個環境的特定配置檔案,我們可以更輕鬆地在 foo/settings/base.py檔案中新增和刪除應用。例如,你可能只想在dev環境而不是其他環境中安裝Django除錯工具欄。

這個技巧對 TEMPLATE_DIRSMIDDLEWARE_CLASSES 配置也非常有用。

我們經常使用的另一個技巧是把應用分為兩個列表,一個是專案的必要前提,另一個用於實際專案應用。如下面所示:

為什麼這個有用?第一,它有助於更好地區分Django核心應用、第三方應用及你自己的內部專案的具體應用。對於測試和程式碼覆蓋率等事情,寫明你的特定應用的PROJECT_APPS列表往往就派上了用場。你有寫一個應用列表,因此你可以輕鬆自動地確保它們的測試執行,記錄的測試覆蓋率只包括它們而不包括任何第三方的應用,且無需在兩個不同的地方維護這個列表。

修改要求

大多是專案有一個requirements.txt檔案,它用如下命令安裝:

對於簡單的小專案這以足夠了,但requirements.txt檔案有一個鮮為人知的特點是,你可以使用-r引數來包括其他檔案。因此,對於所有常見的安裝要求,我們可以建立一個base.txt檔案;然後,如果我們需要能夠執行測試,我們可以建立一個包含如下內容的特定的requirements/test.txt檔案:

我承認這沒有巨大的好處,但它確實有助於區分什麼是每個開發環境的要求。同時,對於其效能,它不會安裝一堆在實際生產中用不上的東西,來減少生產環境中的pip安裝時間。

測試檔案

我們為什麼要拆分很大的測試檔案呢?其中的一個主要原因是,如果你在一個tests.py檔案中對每個應用寫了足夠多的測試,那麼這個檔案最終將變得非常臃腫。這樣的程式碼可讀性很差,並且你不得不在編輯器中花很多時間來滾動瀏覽程式碼。

當你和其他開發者一起工作時,小檔案也能讓你在程式碼合併時少遇到衝突。小檔案是你的朋友。

URLs

對於小型專案,把所有的URL定義放在foo/urls.py檔案中,讓它們在同一個地方。但是,如果你的目標是程式碼的清晰和可複用,你最好在每個應用中定義它們的url,再將它們包含在你的主專案中。你不應如下所做:

你應該這樣做:

模板和靜態資源

每個應用中都有templates/static/目錄,這讓一個應用可以基本上覆用到其他的專案中。

對於一個很酷的功能,我們全在一個包中獲得應用提供的預設模板和任何相關的靜態資源,如特殊的Javascript。

但是,它也讓我們可以覆寫每個專案主目錄foo/templates/下的模板。我們通過增加一個 templates/blog/detail.html 模板覆寫預設的 blog/templates/blog/detail.html 模板。

複用Django應用

假設你已經使用這個佈局一段時間,有一天你會意識到你的新專案需要一個blog應用,這個從你的foo專案出來的應用將是完美的。所以你複製、貼上檔案……錯誤!現在你有這個應用的兩個副本。假定你還記得,在一個副本中進行Bug修復和新功能增添需要手動地在專案間遷移。

相反,為你的部落格建立一個新的目錄,並把foo/blog/目錄中的內容放入其中。同時,調整現有的foo專案和你的新專案來進行安裝。

如果需要的話,它們仍然可以跟蹤這兩個不同版本的應用,或持續更新,且獲得它們不斷髮展中的所有bug修復和新功能。你仍然可以在每個專案的基礎上,根據需求覆寫模板和靜態資源,所以這樣做真的沒有任何問題。

其他資源

我們的朋友 Danny 和 Audrey 在 CartWheel Web上向我們推薦了Cookie Cutter,特別是Danny的cookiecutter-django,它是一個簡單可重複初始化專案的有用的工具。

另外,如果你正在各處尋找很好的 Django 建議和最佳實踐,那你不要錯過了他們的書:《Two Scoops of Django: Best Practices For Django 1.6》。

反饋

我們希望你能發現這個改良後的專案佈局非常有用。如果您發現任何錯誤、或有一些建議、或只是想聊聊,可以隨時聯絡我們。感謝您的閱讀!

相關文章