天天看點

Django部落格教程(五):處理 http 請求完全解讀

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

我們打開浏覽器,在位址欄輸入我們想通路的網址,比如 www.djangoproject.com(當然你也可能從收藏夾裡直接打開網站,但本質上都是一樣的。)

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

網站伺服器處理了 http 請求,然後生成一段 http 響應給浏覽器,浏覽器解讀這個響應,把相關的内容在浏覽器裡顯示出來,于是我們就看到了網站的内容。比如你通路了社群首頁 www.pythonzh.cn,伺服器接收到這個請求後他就知道使用者通路的是首頁,首頁顯示的是全部文章清單,于是它從資料庫裡把文章資料取出來,生成一個寫着這些資料的 html 文檔,包裝到 http 響應裡發給浏覽器,浏覽器解讀這個響應,把 html 文檔顯示出來,我們就看到了文章清單的内容。

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

django 如何接收 http 請求?

django 如何處理這個 http 請求?

django 如何生成 http 響應?

對于如何處理這些問題,django 有其自身的一套規定的機制。我們按照 django 的規定,就能開發出我們所需的功能。我們先以一個最簡單的 hello world 為例來看看 django 處理上述問題的機制是怎麼樣的。

首先 django 需要知道當使用者通路不同的網址時,應該如何處理不同的網址。django 的做法是把不同的網址對應的處理函數寫在一個 urls.py 檔案裡,當使用者通路某個網址時,django 就去會這個檔案裡找,如果找到這個網址,就會調用和它綁定在一起的處理函數(叫做視圖函數),下面是具體的做法,首先在 blog 應用的目錄下建立一個 urls.py 檔案,這時你的目錄看起來是這樣:

Django部落格教程(五):處理 http 請求完全解讀

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

Django部落格教程(五):處理 http 請求完全解讀

我們首先從 django.conf.urls 導入了 url 函數,又從目前目錄下導入了 views 子產品。然後我們把網址和處理函數的關系寫在了 urlpatterns 清單裡。綁定關系的寫法是把網址和對應的處理函數作為參數傳給 url 函數(第一個參數是網址,第二個參數是處理函數),另外我們還傳遞了另外一個參數 name,這個參數的值将作為處理函數 index 的别名,這在以後會用到。

注意這裡我們的網址是用正規表達式寫的,django 會用這個正規表達式去比對使用者實際輸入的網址,如果比對成功,就會調用其後面的視圖函數做相應的處理。比如說我們本地開發伺服器的域名是 127.0.0.1:8000,那麼當使用者輸入網址:127.0.0.1:8000 後,django 首先會把域名(即 127.0.0.1)和端口号(8000)去掉,此時隻剩下一個空字元串,而 r'^$' 的模式正是比對一個空字元串(這個正規表達式的意思是以空字元串開頭且以空字元串結尾),于是二者比對,django 便會調用其對應的 views.index 函數。

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

Django部落格教程(五):處理 http 請求完全解讀

我們前面說過,Web 伺服器的作用就是接收來自使用者的 http 請求,根據請求内容作出相應的處理,并把處理結果包裝成 http 響應傳回給使用者。這個兩行的函數展現了這個過程。它首先接受了一個名為 request 的參數,這個 request 就是 django 為我們封裝好的 http 請求,它是類 HttpResponse 的一個執行個體。然後我們便直接傳回了一個 http 響應給使用者,這個 http 響應也是 django 幫我們封裝好的,它是類 HttpResponse 的一個執行個體,隻是我們給它傳了一個自定義的字元串,使用者接受到這個響應後就會在浏覽器顯示出我們傳遞的内容:“歡迎通路我的部落格首頁!”

還差最後一步了,我們前面建立了一個 urls.py 檔案,并且綁定了 URL 和視圖函數 index,但是 django 并不知道。django 比對 url 是在 blogproject 的 urls.py 下的,是以我們要把我們自己寫的 urls.py 檔案包含到這個檔案裡去,打開這個檔案看到如下内容:

Django部落格教程(五):處理 http 請求完全解讀

修改成如下的形式:

Django部落格教程(五):處理 http 請求完全解讀

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

這基本上就上 django 的開發流程了,寫好處理 http 請求和傳回 http 響應的視圖函數,然後把視圖函數綁定到相應的 URL 上。但是等一等!我們看到在我們的視圖函數裡傳回的是一個 HTTPResponse 類的執行個體,我們給他傳入了一個我們希望顯示在使用者浏覽器上的字元串。但是我們的部落格不可能隻顯示這麼一句話,它有可能會顯示很長很長的内容,比如我們釋出的部落格文章清單,或者一大段的部落格文章,我們不能每次都把這些大段大段的内容傳給 HTTPResponse。于是 django 對這個問題給我們提供了一個好的方法,叫做模闆系統。django 要我們把大段的文本寫到一個檔案裡,然後 django 自己會去讀取這個檔案,django 再把讀取到的内容傳給 HTTPResponse。我們用模闆系統來改造一下上面的例子。首先在我們的項目根目錄下建立一個名為 templates 的檔案夾,用來存放我們的模闆。然後再建立一個名為 blog 的檔案夾,用來存放和 blog 應用相關的模闆。當然模闆存放在哪裡是無關緊要的,隻要 django 能夠找到的就好。但是我們建立這樣的檔案夾結構的目的是把不同應用用到的模闆隔離開來,這樣友善以後維護,養成良好的習慣。然後我們在 blog 目錄下建立一個名為 index.html 的檔案,寫上下面的代碼:

Django部落格教程(五):處理 http 請求完全解讀

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

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

Django部落格教程(五):處理 http 請求完全解讀

其中 DIRS 就是設定模闆的路徑,在 [] 中寫入 os.path.join(BASE_DIR, 'templates'),變成這樣:

Django部落格教程(五):處理 http 請求完全解讀

這裡 BASE_DIR 是 settings.py 前面定義的變量,記錄的是工程根目錄 blogproject 的值,在這個目錄下有我們的模闆目錄 templates,于是利用os.path.join 把這兩個路徑連起來,構成完整的模闆路徑,django 就知道去這個路徑下面找我們的模闆了。

視圖函數可以改一下了:

Django部落格教程(五):處理 http 請求完全解讀

這裡我們在是直接把字元串傳給 HttpResponse 了,而是調用 django 提供了 render 函數,這個函數根據我們傳入的參數來構造 HttpResponse。我們首先把 http 請求傳了進去,然後它根據第二個參數的值 blog/index.html 找到我們的模闆,然後讀取模闆中的内容,并且根據我們傳入的 context 把模闆中的變量替換為我們傳遞的值,{{ title }} 被替換成了 context 字典中 title 對應的值,同理 {{ welcome }} 也被替換成相應的值。最終,我們的 html 模闆中的内容字元串被傳遞給 HttpResponse 對象并傳回給浏覽器,這樣使用者的浏覽器上便顯示出了我們寫的 html 模闆的内容。

原文釋出時間為:2017-05-07

本文作者:追夢人物

上一篇: LAMP架構講解