Django作為一款功能強大的Web應用框架,近年來逐步受到大家的歡迎,越來越多的Python開發者投入到Django的懷抱中,但是同樣由於Django中的眾多內容,大家在初入Django時總會感到有一些‘心有餘而力不足’,不知道從何處下手。或者在初步了解之後,仍不確定當前方法是否優雅,不知道如何組織項目,以及如何使程式碼重用性更高。
好的專案結構是成功的一半。
在預設情況下,由Django產生的專案結構大概是這樣的:
venv資料夾存放項目的virtualenv環境,非必須,可放置在其他地方。 database這個App專門用來存放model、manage的指令、以及範本中用到的一些自訂filters,存放在專案根目錄下。 docs和logs分別存放工程的相關文件和執行時產生的log檔案。 static存放靜態文件,例如css/js/img/font等。 utils存放工程中用到的工具函數、類,以及一些通用的模組,例如logger等。 templates存放模板文件,父模板或被多個模板繼承的模板放在根目錄,並且以base之類的名稱命名,方便維護,其餘的模板放在對應的application名字的文件夾中。 web目錄存放所有的Application,如果有很多的Application,可以在此基礎上分成更多的package來規劃,每個package裡存放一類的Application。2.2 Model在Model模組部分,我們主要關心資料到類別的映射,一般情況下,每張表對應的類別將放置在單獨的檔案中,並在models/__init__.py中將對應的類別依次導入,這樣在其他地方使用時可以透過from database.models import xxxx導入,給類別命名時建議添加上項目的名稱,例如我這裡有個項目的名字是Cherry,那麼所有的類別均為CherryLeaks,CherryVulns等,在reivew程式碼以及編寫的過程中會一目了然,知道這個類別代表了資料。 建議為Models新增單獨的manager,並實作對應的方法,以避免重複操作。 除此之外,還有一些建議,可以根據實際情況取捨:
不建議使用外鍵等類型每張表添加is_deleted, created_time,updated_time欄位善用索引2.3 View大多數業務邏輯應該放在View部分,此部分應該是最核心的。這裡也是推薦將功能相近的View全部放置在同一個檔案中。方便未來的維護和開發,該文件應放置於名為 "controller" 或 "view" 的包中。例如處理project相關的路由,全部放置在controller/project.py中。 優先使用Django內建的一些View類,例如ListView,TemplateView等,如果需要自己實作View的情況,建議使用Class-based view,將不同的請求方法封裝到不同的方法中,方便日後維護。 2.4 Template對於模板文件而言,最好的方法就是將不同的頁面、功能切割為不同的模板文件,並按Applicatio的名稱按文件夾存放,這樣在後期維護時,可以快速的從每個Application找到對應的模板檔案。 除此之外,強烈建議使用模板的繼承功能,所有的頁面均從父模板繼承下來,並且使用各種block來擴充頁面,父模板中定義好每個位置的block名稱,供子模板覆蓋。建議使用通俗簡短的名稱為每個block命名,例如:sidebar,script,header,main_content,page_title,page_description等。 對於通用的功能,例如評論框,可以考慮單獨存放在一個檔案中,在需要的地方透過{% include 'filename.tpl.html' %}載入。要注意的是,如果你需要同時使用extends和include指令,一定要在block中使用,否則是無效的。如下範例是無效的:
Python語言的彈性,使得我們有時會在寫程式碼時忘記特定方法的參數類型或傳回類型。在此情況下,我們需要使用docstring為每個方法提供清晰的資訊標註,以便其他人可以開發和維護。參考這個鏈接,如果你在使用PyCharm,可以編寫自動補全docstring。
很多情況下,我們的方法需要傳回多個值給呼叫方,或透過JSON回傳給前端,如果胡亂的回傳數據,就會導致開發混亂,到最後根本不知道方法回傳了什麼東西。
一個比較好的做法就是約定好回傳的格式,對於傳回給呼叫方而言,簡單的回傳tuple即可,並在docstring中寫明每個值的意義。除了傳回結果,有時我們需要傳回一個err,以表示在處理資料過程中是否出現了問題或異常。一般情況下有幾種可用的方法:
透過raise拋出異常
透過多重傳回值返回,例如err, result = func()
透過類別中的一個屬性傳回,例如instance = Class(); err = instance.error_message
這三種方法都有好弊,需要根據專案的實際情況來選取,無論使用哪一種方法,都需要在整個專案中保持統一,盡可能的不要混合使用;
對於傳回前端的JSON,就需要稍微複雜一些,至少要回傳2~3個欄位:
code是本次呼叫傳回的狀態碼,根據實際情況自行約定。 message 是狀態碼的易於理解的訊息,可供開發人員調試並向使用者提供通知。 data是實際傳回的資料訊息,很多時候可以不需要這個字段,具體的字段格式也需要根據實際情況再次進行約定。
優雅簡單的路由保證專案質量,降低維護成本。
Django有一套強大的路由系統以及路由演算法,可以滿足業務中的各種需要,並且配置靈活簡單,每個路由設定檔都是URL PATH到function/class的對應。全部都可以自己設置,完全不會受到框架或其他的一些限制。可以參考文件中關於Django請求路由尋找策略的這一部分。
在設定路由中,你可以用尖括號括起來一些變量,方便在後面使用。尖括號裡可以用一些"路徑轉換器(Path Converters)"來指定變數類型,例如str, int, slug, uuid, path。一個完整的URL路由檔案看起來像下面這樣:
除此之外,還可以透過re_path在路由中設定正規匹配:
有些時候,你可能想要為一些URL添加一個預設路由,例如訪問/blog/的時候返回一個預設頁面,而訪問/blog/page
隨著專案的不斷擴大,使用的路由也會不斷的變多,所以Django提供了路由包含的機制,讓我們在不同的App中組織路由。讓我們來看一個簡單的例子:
這個例子中,將所有請求community/*的路由全部交由aggregator.urls去解析,同理, contact/*的請求也全部交給了另外的路由模組去處理;如果你的專案中並沒有這麼多的Application,仍然想透過include的方式來管理路由,那麼可以採用如下方式:
一般情況下,我們的每個Django專案都由多個App組成,如果把所有App的路由全部放在URLCONF_ROOT裡,時間久了這個文件會變的越來越難維護,十分混亂。在不同的App中可能會使用相同名稱的路由,導致衝突。為了解決這些問題,我們可以透過使用"路由包含"和"命名空間"來解決,特別是如果你在維護一個可以被重複使用的App,為了確保路由的唯一,命名空間就顯得尤為重要了。
命名空間通常有兩種:Application namespace和Instance namespace,例如admin:index表示admin命名空間的index路由。更多關於該部分的內容可以參考:官方文件
Application Namespace比較好理解,指的是應用程式層面上的命名空間,一般是如下方式組織的:
Instance Namespace則指的是實例層級的命名空間,常用於一個App被多次實例化的情況,為了區分每個實例,就需要引入Instance Namespace。我們使用官方文件中的範例來看看:
可以看到兩個路由author-polls和publisher-polls其實都包含了相同的路由,但指定了不同的命名空間,這就是Instance層級的命名空間,也就是目前正在存取的物件的命名空間。不同的使用者身分存取不同的URL,會得到不同的命名空間,例如遊客和管理員均造訪polls:index所指向的頁面,但由於命名空間的不同,會得到完全不同的結果。
以上是Django開發方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!