Django作為一個龐大的亡嫌、自帶電池的、整體Web開發(fā)解決方案框架掘而,源代碼多、子系統(tǒng)多于购、工具多袍睡。要將如此多的內(nèi)容集成到一起,必然需要一個指導(dǎo)性的設(shè)計理念和哲學(xué)思維肋僧。這樣才不至于顯得東拼西湊斑胜、雜亂無章控淡、接口混亂,而是整體一致止潘、思路清晰掺炭、邏輯合理。既方便了源碼開發(fā)凭戴,也方便了應(yīng)用開發(fā)涧狮。
下面就介紹一下Django的設(shè)計理念和哲學(xué)思維,這其中有一些是Django源代碼中正在遵循的么夫,一些是使用者開發(fā)項目過程中需要遵循的:
系統(tǒng)性原則
松耦合
Django 追求各子系統(tǒng)(層)的低耦合和高內(nèi)聚者冤。各層之間保持代碼獨立、功能獨立档痪、盡量沒有交聯(lián)涉枫。
例如,模板層不需要知道用戶的 Web 請求具體情況腐螟,模型層不需要了解模板層是如何展示數(shù)據(jù)的愿汰,視圖層也不關(guān)心程序員所使用的模板系統(tǒng)到底是哪種和怎么使用的。通俗地說乐纸,模型層只關(guān)心數(shù)據(jù)的CRUD衬廷,視圖層只負責(zé)業(yè)務(wù)邏輯的實現(xiàn),模板層只管前端頁面的渲染和展示锯仪。這三個核心層之間只有數(shù)據(jù)的傳遞泵督,沒有代碼的交互,各自相對獨立庶喜。
更少的代碼
Django 建議每個APP的代碼應(yīng)該盡可能地精簡小腊,應(yīng)該充分利用 Python 的動態(tài)能力,比如自省機制(introspection)久窟。
快速開發(fā)
Django誕生于一個新聞編輯社秩冈,其應(yīng)用環(huán)境要求快速開發(fā)和迅速迭代,所以在設(shè)計之初就追求以更快的速度實現(xiàn)需求的處理斥扛,你只需要編寫一些新代碼入问,或者修改一些局部代碼就可以實現(xiàn)新的站點。
不要重復(fù)地造輪子 (DRY)
除非有特殊需求稀颁,所有官方或者生態(tài)圈內(nèi)已經(jīng)提供的庫芬失、工具、插件和功能匾灶,請直接拿來使用棱烂,不要自己開發(fā)。
明確優(yōu)于隱式
這條原則的根本意思是:不要玩花招阶女、炫技巧颊糜,盡可能用更普通哩治、更明確、更直觀的語法衬鱼,不要使用那些晦澀難懂的語法业筏。將你的代碼寫得更啰嗦、更直白鸟赫、更清晰蒜胖,多兩行不怕,多點注釋更好惯疙。
一致性
框架應(yīng)在所有層級上保持一致翠勉。一致性適用于從低級(Python 的編碼風(fēng)格)到高級(使用 Django 的“經(jīng)驗”)的所有內(nèi)容。
這條規(guī)則既有代碼規(guī)范上的要求霉颠,也有開發(fā)習(xí)慣的要求对碌,要在整個項目中保持統(tǒng)一的風(fēng)格。代碼如其人蒿偎,程序員是個什么樣的性子和思路朽们,在代碼里能看得清清楚楚。要保持人設(shè)的統(tǒng)一性诉位,不要前面是狂野粗放的大漢骑脱,后面是裹腳布又臭又長,這樣不好苍糠,讓人以為代碼是好多不同的人寫的叁丧,沒有一個統(tǒng)一的章法。
模型層相關(guān)
明確優(yōu)于隱式
字段不應(yīng)該僅僅根據(jù)字段的名稱來假定某些行為岳瞭。這需要對系統(tǒng)有太多了解拥娄,并且容易出現(xiàn)錯誤。相反瞳筏,其行為應(yīng)該基于關(guān)鍵字參數(shù)稚瘾,并且在某些情況下,應(yīng)該基于字段的類型姚炕。
白話說就是:不要通過字段的名稱上來指定它的功能摊欠,而應(yīng)該通過詳細、明確地選擇字段的類型柱宦,定義字段的參數(shù)來設(shè)計字段些椒。
模型應(yīng)當(dāng)包含所有信息
模型中應(yīng)該封裝一個“對象”的各個方面,并遵循 Martin Fowler 的 Active Record 設(shè)計模式掸刊。
也就是說免糕,對于一個模型,任何與之相關(guān)的元信息、方法说墨、函數(shù)、屬性苍柏,包括其人類可讀的名稱尼斧,默認排序等選項,這些所有用于理解該模型所需的信息试吁,都應(yīng)該存儲在模型中棺棵,而不要將它們放到視圖、URL或者模板中去實現(xiàn)熄捍。
ORM相關(guān)
提高SQL效率
應(yīng)該盡可能少地執(zhí)行SQL語句烛恤,并且應(yīng)該在內(nèi)部優(yōu)化語句。
開發(fā)者需要顯式地調(diào)用 save()余耽,而不是由框架靜默地在幕后保存數(shù)據(jù)缚柏。
API應(yīng)該簡潔并強大
ORM的API 應(yīng)該允許用盡可能少的語法,來表達豐富碟贾、達意的語句币喧。它不應(yīng)該依賴于導(dǎo)入其他模塊或輔助對象。
每一個對象都應(yīng)該能夠訪問所有相關(guān)的對象袱耽,和系統(tǒng)范圍杀餐,并且這種訪問應(yīng)該是雙向的。
支持使用原生 SQL 語句
ORM的API 只是一個便捷的方法朱巨,但并不是最終的全部手段史翘,框架必須支持使用原生SQL語句,這一點Django做到了冀续。
URL 設(shè)計相關(guān)
松耦合
Django 應(yīng)用中的 URL 不應(yīng)該與底層 Python 代碼耦合琼讽。將 URL 與 Python 函數(shù)名聯(lián)系起來是一件很糟糕且丑陋的做法。
也就是說沥阳,APP中的視圖到底干什么跨琳,和你的URL到底寫成啥樣沒有關(guān)系,不能將URL和APP捆在一起綁死了桐罕。例如脉让,一個網(wǎng)站可以在 /stories/ 中放置故事,而另一個網(wǎng)站則可以使用 /news/來放置故事功炮,兩種不同的URL其背后的APP是一樣的溅潜,我雖然復(fù)用了APP,但我可以使用另外一套URL去映射它薪伏。
無限的靈活性
URL 應(yīng)該盡可能靈活滚澜。任何可想到的 URL 設(shè)計都應(yīng)該被允許。
URL應(yīng)該優(yōu)雅
設(shè)計漂亮的URL嫁怀,而不是難看的 URL设捐。
在 URL 中應(yīng)避免出現(xiàn)文件后綴名借浊。
在 URL 中不應(yīng)使用 Vignette 式的逗號。
最后的斜杠
從技術(shù)上而言萝招,foo.com/bar
和 foo.com/bar/
是兩條不同的 URL蚂斤,搜索引擎爬蟲(以及某些 Web 流量分析工具)會將其視為獨立的兩個頁面。但是Django 會將其轉(zhuǎn)為 "標(biāo)準" 的 URL槐沼,讓搜索引擎爬蟲正確識別曙蒸。詳細參考 APPEND_SLASH
配置。
模板系統(tǒng)相關(guān)
邏輯分離的解決方案
我們將模板系統(tǒng)看作一個工具岗钩,用于控制表現(xiàn)方式和表示方式相關(guān)的邏輯纽窟。模板系統(tǒng)不應(yīng)該支持超出這個基本目標(biāo)的功能。
避免冗余
大多數(shù)動態(tài)網(wǎng)站會使用一些網(wǎng)站整體通用的設(shè)計兼吓,比如通用的頁眉臂港、頁腳、導(dǎo)航欄等等周蹭。Django 模板系統(tǒng)遵循了這一點趋艘,可以很容易地將這些元素存儲在一個地方,從而減少重復(fù)的代碼凶朗。
從 HTML 中解耦
模板系統(tǒng)不應(yīng)該被設(shè)計成只能輸出 HTML瓷胧。它應(yīng)該同樣擅長生成其他基于文本的格式,或者僅僅是純文本棚愤。
XML不應(yīng)被用于模板語言
使用 XML 引擎去解析模板會在編輯模板的過程中引入很多人為錯誤搓萧,并在模板處理中導(dǎo)致不可接受的開銷。
不要指望模板系統(tǒng)能包打天下
Django 期望模板編寫者有能力直接編輯 HTML 文本宛畦。
更加直接的處理空格
模板系統(tǒng)不應(yīng)該用空白符來做神奇的事情瘸洛。如果模板包含空白符,系統(tǒng)應(yīng)該在處理文本時處理空格——只是顯示它次和。任何不在模板標(biāo)簽中的空白符都應(yīng)該顯示出來反肋。
不要發(fā)明一種編程語言
模板系統(tǒng)的目標(biāo)不是發(fā)明一種編程語言。它的目標(biāo)是提供足夠的具有編程風(fēng)格的功能踏施,比如分支和循環(huán)石蔗,這對于做出表現(xiàn)相關(guān)的決策是至關(guān)重要的。Django 模板語言(DTL) 旨在避免高級邏輯畅形。
Django 模板系統(tǒng)認為模板通常是由 設(shè)計師 編寫的养距,而不是 程序員,因此不應(yīng)該假設(shè)他了解 Python日熬。
所以棍厌,我們在使用Django的模板系統(tǒng)時會發(fā)現(xiàn),這只是一個具有一般編程功能的渲染工具,不要妄圖把它當(dāng)作一個功能強大耘纱、語法完整的編程語言來使用敬肚。
安全與保障
開箱即用的模板系統(tǒng)禁止包含惡意代碼,例如刪除數(shù)據(jù)庫記錄的代碼束析。
這也是模板系統(tǒng)不允許有任意Python代碼的另一個原因帘皿。
可擴展性
模板系統(tǒng)應(yīng)該認識到, 高階的模板作者可能想擴展它。
這是自定義的模板標(biāo)簽和過濾器背后的理念畸陡。
視圖
盡量簡潔
編寫視圖應(yīng)該和編寫 Python 函數(shù)一樣簡單。開發(fā)人員不應(yīng)該在函數(shù)執(zhí)行時實例化一個類虽填。
使用請求對象
視圖應(yīng)該能夠訪問一個請求對象——一個儲存關(guān)于當(dāng)前請求的元數(shù)據(jù)的對象丁恭。對象應(yīng)該直接傳遞給視圖函數(shù),而不是必須從全局變量訪問請求數(shù)據(jù)的視圖函數(shù)斋日。這使得通過傳入“假”請求對象來測試視圖變得輕松牲览、干凈和容易。
根據(jù)這條理念恶守,Django每個視圖函數(shù)的第一個參數(shù)都是request第献,從這個request中,我們可以拿到所有用戶請求相關(guān)的數(shù)據(jù)兔港。
松耦合
視圖不應(yīng)該關(guān)心開發(fā)人員使用哪種模板——甚至根本不用模板系統(tǒng)庸毫。
GET 方法和 POST 方法的區(qū)別
GET 和 POST 是不同的;開發(fā)人員應(yīng)該明確地使用其中一個或另一個衫樊§撸框架應(yīng)該使得 GET 和 POST 數(shù)據(jù)很容易區(qū)分。
所以科侈,在使用函數(shù)型視圖的時候载佳,應(yīng)該明確地寫明:if request.method=='GET':pass
,而不要使用默認的函數(shù)執(zhí)行順序臀栈。
緩存框架相關(guān)
緩存框架 的核心目的是:
更少的代碼
緩存應(yīng)該盡可能快蔫慧。因此,圍繞緩存后端的所有框架代碼都應(yīng)該保持在絕對的最小值权薯,特別是對于 get() 操作姑躲。
一致性
緩存 API 應(yīng)該為不同的緩存后端提供一致的接口。
可擴展性
緩存 API 應(yīng)該基于開發(fā)者的需求崭闲,在應(yīng)用程序級別上是可擴展的(例如肋联,參見 Cache key transformation)。