天天看點

Django 部落格開發教程 5 - Django 部落格首頁視圖

web 應用的互動過程其實就是 http 請求與響應的過程。無論是在 pc 端還是移動端,我們通常使用浏覽器來上網,上網流程大緻來說是這樣的:

浏覽器知道我們想要通路哪個網址後,它在背景幫我們做了很多事情。主要就是把我們的通路意圖包裝成一個 http 請求,發給我們想要通路的網址所對應的伺服器。通俗點說就是浏覽器幫我們通知網站的伺服器,說有人來通路你啦,通路的請求都寫在 http 裡了,你按照要求處理後告訴我,我再幫你回應他!

是以,django 作為一個 web 架構,它的使命就是處理流程中的第二步。即接收浏覽器發來的 http 請求,傳回相應的 http 響應。于是引出這麼幾個問題:

django 如何接收 http 請求?

django 如何處理這個 http 請求?

django 如何生成 http 響應?

對于如何處理這些問題,django 有其一套規定的機制。我們按照 django 的規定,就能開發出所需的功能。

我們先以一個最簡單的 hello world 為例來看看 django 處理上述問題的機制是怎麼樣的。

首先 django 需要知道當使用者通路不同的網址時,應該如何處理這些不同的網址(即所說的路由)。django 的做法是把不同的網址對應的處理函數寫在一個 urls.py 檔案裡,當使用者通路某個網址時,django 就去會這個檔案裡找,如果找到這個網址,就會調用和它綁定在一起的處理函數(叫做視圖函數)。

下面是具體的做法,首先在 blog 應用的目錄下建立一個 urls.py 檔案,這時你的目錄看起來是這樣:

在 blogurls.py 中寫入這些代碼:

我們首先從 django.conf.urls 導入了 <code>url</code> 函數,又從目前目錄下導入了 views 子產品。然後我們把網址和處理函數的關系寫在了 <code>urlpatterns</code> 清單裡。

綁定關系的寫法是把網址和對應的處理函數作為參數傳給 <code>url</code> 函數(第一個參數是網址,第二個參數是處理函數),另外我們還傳遞了另外一個參數 <code>name</code>,這個參數的值将作為處理函數 <code>index</code> 的别名,這在以後會用到。

注意這裡我們的網址是用正規表達式寫的,django 會用這個正規表達式去比對使用者實際輸入的網址,如果比對成功,就會調用其後面的視圖函數做相應的處理。

注意:在項目根目錄的 blogproject 目錄下(即 settings.py 所在的目錄),原本就有一個 urls.py 檔案,這是整個工程項目的 url 配置檔案。而我們這裡建立了一個 urls.py 檔案,且位于 blog 應用下。這個檔案将用于 blog 應用相關的 url 配置。不要把兩個檔案搞混了。

第二步就是要實際編寫我們的 <code>views.index</code> 視圖函數了,按照慣例視圖函數定義在 views.py 檔案裡:

我們前面說過,web 伺服器的作用就是接收來自使用者的 http 請求,根據請求内容作出相應的處理,并把處理結果包裝成 http 響應傳回給使用者。

這個兩行的函數展現了這個過程。它首先接受了一個名為 <code>request</code> 的參數,這個 <code>request</code> 就是 django 為我們封裝好的 http 請求,它是類 <code>httprequest</code> 的一個執行個體。然後我們便直接傳回了一個 http 響應給使用者,這個 http 響應也是 django 幫我們封裝好的,它是類 <code>httpresponse</code> 的一個執行個體,隻是我們給它傳了一個自定義的字元串參數。

浏覽器接收到這個響應後就會在頁面上顯示出我們傳遞的内容 :歡迎通路我的部落格首頁!

還差最後一步了,我們前面建立了一個 urls.py 檔案,并且綁定了 url 和視圖函數 <code>index</code>,但是 django 并不知道。django 比對 url 模式是在 blogproject 目錄(即 settings.py 檔案所在的目錄)的 urls.py 下的,是以我們要把 blog 應用下的 urls.py 檔案包含到 blogprojecturls.py 裡去,打開這個檔案看到如下内容:

修改成如下的形式:

這裡 - 表示删掉這一行,+ 表示添加這一行。

我們這裡導入了一個 <code>include</code> 函數,然後利用這個函數把 blog 應用下的 urls.py 檔案包含了進來。此外 include 前還有一個 <code>r''</code>,這是一個空字元串。這裡也可以寫其它字元串,django 會把這個字元串和後面 include 的 urls.py 檔案中的 url 拼接。比如說如果我們這裡把 <code>r''</code> 改成 <code>r'blog/'</code>,而我們在 blog.urls 中寫的 url 是 <code>r'^$'</code>,即一個空字元串。那麼 django 最終比對的就是 blog/ 加上一個空字元串,即 blog/。

歡迎通路我的部落格首頁!

這基本上就上 django 的開發流程了,寫好處理 http 請求和傳回 http 響應的視圖函數,然後把視圖函數綁定到相應的 url 上。

但是等一等!我們看到在視圖函數裡傳回的是一個 <code>httpresponse</code> 類的執行個體,我們給它傳入了一個希望顯示在使用者浏覽器上的字元串。但是我們的部落格不可能隻顯示這麼一句話,它有可能會顯示很長很長的内容。比如我們釋出的部落格文章清單,或者一大段的部落格文章。我們不能每次都把這些大段大段的内容傳給 <code>httpresponse</code>。

django 對這個問題給我們提供了一個很好的解決方案,叫做模闆系統。django 要我們把大段的文本寫到一個檔案裡,然後 django 自己會去讀取這個檔案,再把讀取到的内容傳給 <code>httpresponse</code>。讓我們用模闆系統來改造一下上面的例子。

首先在我們的項目根目錄(即 manage.py 檔案所在目錄)下建立一個名為 templates 的檔案夾,用來存放我們的模闆。然後在 templates 目錄下建立一個名為 blog 的檔案夾,用來存放和 blog 應用相關的模闆。

當然模闆存放在哪裡是無關緊要的,隻要 django 能夠找到的就好。但是我們建立這樣的檔案夾結構的目的是把不同應用用到的模闆隔離開來,這樣友善以後維護。我們在 templatesblog 目錄下建立一個名為 index.html 的檔案,此時你的目錄結構應該是這樣的:

再一次強調 templates 目錄位于項目根目錄,而 index.html 位于 templatesblog 目錄下,而不是 blog 應用下,如果弄錯了你可能會得到一個templatedoesnotexist 異常。如果遇到這個異常,請回來檢查一下模闆目錄結構是否正确。

在 templatesblogindex.html 檔案裡寫入下面的代碼:

這是一個标準的 html 文檔,隻是裡面有兩個比較奇怪的地方:<code>{{ title }}</code>,<code>{{ welcome }}</code>。這是 django 規定的文法。用 {{ }} 包起來的變量叫做模闆變量。django 在渲染這個模闆的時候會根據我們傳遞給模闆的變量替換掉這些變量。最終在模闆中顯示的将會是我們傳遞的值。

注意:index.html 必須以 utf-8 的編碼格式儲存,且小心不要往裡面添加一些特殊字元,否則極有可能得到一個 unicodedecodeerror 這樣的錯誤。

模闆寫好了,還得告訴 django 去哪裡找模闆,在 settings.py 檔案裡設定一下模闆檔案所在的路徑。在 settings.py 找到 <code>templates</code> 選項,它的内容是這樣的:

其中 <code>dirs</code> 就是設定模闆的路徑,在 [] 中寫入 <code>os.path.join(base_dir, 'templates')</code>,即像下面這樣:

這裡 <code>base_dir</code> 是 settings.py 在配置開頭前面定義的變量,記錄的是工程根目錄 blogproject 的值(注意是最外層的 blogproject 目錄)。在這個目錄下有模闆檔案所在的目錄 templates,于是利用<code>os.path.join</code> 把這兩個路徑連起來,構成完整的模闆路徑,django 就知道去這個路徑下面找我們的模闆了。

視圖函數可以改一下了:

這裡我們不再是直接把字元串傳給 <code>httpresponse</code> 了,而是調用 django 提供的 <code>render</code> 函數。這個函數根據我們傳入的參數來構造 <code>httpresponse</code>。

我們首先把 http 請求傳了進去,然後 <code>render</code> 根據第二個參數的值 blog/index.html 找到這個模闆檔案并讀取模闆中的内容。之後 <code>render</code> 根據我們傳入的 <code>context</code> 參數的值把模闆中的變量替換為我們傳遞的變量的值,<code>{{ title }}</code> 被替換成了 <code>context</code> 字典中 <code>title</code> 對應的值,同理 <code>{{ welcome }}</code> 也被替換成相應的值。

最終,我們的 html 模闆中的内容字元串被傳遞給 <code>httpresponse</code> 對象并傳回給浏覽器(django 在 <code>render</code> 函數裡隐式地幫我們完成了這個過程),這樣使用者的浏覽器上便顯示出了我們寫的 html 模闆的内容。

如果遇到問題,請通過下面的方式尋求幫助。

将問題的較長的描述通過郵件發送到 [email protected],一般會在 24 小時内回複。