Django 博客首頁視圖
Django 處理 HTTP 請求
Web 應用的交互過程其實就是 HTTP 請求與響應的過程令境。無論是在 PC 端還是移動端懊纳,通常使用瀏覽器來上網佑菩,上網流程大致來說是這樣的:
打開瀏覽器离唐,在地址欄輸入想訪問的網址,比如 http://www.baidu.com/
瀏覽器知道我們想要訪問哪個網址后沸毁,它在后臺幫我們做了很多事情峰髓。主要就是把訪問意圖包裝成一個 HTTP 請求,發(fā)給我們想要訪問的網址所對應的服務器息尺。訪問的請求都寫在 HTTP 里了携兵,你按照要求處理后告訴我,我再幫你回應他掷倔!
服務器處理了HTTP 請求眉孩,然后生成一段 HTTP 響應給瀏覽器个绍。瀏覽器解讀這個響應勒葱,把相關的內容在瀏覽器里顯示出來,于是我們就看到了網站的內容巴柿。比如你訪問了 http://www.baidu.com/凛虽,服務器接收到這個請求后就知道用戶訪問的是首頁。
因此广恢,Django 作為一個 Web 框架凯旋,它的使命就是處理流程中的第二步。即接收瀏覽器發(fā)來的 HTTP 請求,返回相應的 HTTP 響應至非。于是引出這么幾個問題:
Django 如何接收 HTTP 請求钠署?
Django 如何處理這個 HTTP 請求?
Django 如何生成 HTTP 響應荒椭?
對于如何處理這些問題谐鼎,Django 有其一套規(guī)定的機制。我們按照 Django 的規(guī)定趣惠,就能開發(fā)出所需的功能狸棍。
Index 視圖函數
先以一個最簡單的 Hello World 為例來看看 Django 處理上述問題的機制是怎么樣的。
綁定 URL 與視圖函數
首先 Django 需要知道當用戶訪問不同的網址時味悄,應該如何處理這些不同的網址(即所說的路由)草戈。Django 的做法是把不同的網址對應的處理函數寫在一個 urls.py 文件里,當用戶訪問某個網址時侍瑟,Django 就會去這個文件里找唐片,如果找到這個網址,就會調用和它綁定在一起的處理函數(叫做視圖函數)丢习。
下面是具體的做法牵触,首先在 blog 應用的目錄下創(chuàng)建一個 urls.py 文件,這時你的目錄看起來是這樣:
在 blog\urls.py 中寫入這些代碼:
首先從 django.conf.urls 導入了url函數咐低,又從當前目錄下導入了 views 模塊揽思。然后把網址和處理函數的關系寫在了urlpatterns列表里。
綁定關系的寫法是把網址和對應的處理函數作為參數傳給url函數(第一個參數是網址见擦,第二個參數是處理函數)钉汗,另外還傳遞了另外一個參數name,這個參數的值將作為處理函數index的別名鲤屡,這在以后會用到损痰。
注意這里的網址是用正則表達式寫的,Django 會用這個正則表達式去匹配用戶實際輸入的網址酒来,如果匹配成功卢未,就會調用其后面的視圖函數做相應的處理。
比如說本地開發(fā)服務器的域名是 http://127.0.0.1:8000堰汉,那么當用戶輸入網址 http://127.0.0.1:8000 后辽社,Django 首先會把協(xié)議 http、域名 127.0.0.1 和端口號 8000 去掉翘鸭,此時只剩下一個空字符串滴铅,而r'^$'的模式正是匹配一個空字符串(這個正則表達式的意思是以空字符串開頭且以空字符串結尾),于是二者匹配就乓,Django 便會調用其對應的views.index函數汉匙。
編寫視圖函數
第二步就是要實際編寫views.index視圖函數了拱烁,按照慣例視圖函數定義在 views.py 文件里:
前面說過,Web 服務器的作用就是接收來自用戶的 HTTP 請求噩翠,根據請求內容作出相應的處理戏自,并把處理結果包裝成 HTTP 響應返回給用戶。
這個兩行的函數體現了這個過程伤锚。它首先接受了一個名為request的參數浦妄,這個request就是 Django 為我們封裝好的 HTTP 請求,它是類HttpRequest的一個實例见芹。然后我們便直接返回了一個 HTTP 響應給用戶剂娄,這個 HTTP 響應也是 Django 幫我們封裝好的,它是類HttpResponse的一個實例玄呛,只是我們給它傳了一個自定義的字符串參數阅懦。
瀏覽器接收到這個響應后就會在頁面上顯示出我們傳遞的內容 :歡迎訪問第一個視圖!
配置項目 URL
還差最后一步了徘铝,我們前面建立了一個 urls.py 文件耳胎,并且綁定了 URL 和視圖函數index,但是 Django 并不知道惕它。Django 匹配 URL 模式是在 blogproject\ 目錄(即 settings.py 文件所在的目錄)的 urls.py 下的怕午,所以要把 blog 應用下的 urls.py 文件包含到 blogproject\urls.py 里去,打開這個文件看到如下內容:
這里導入了一個include函數淹魄,然后利用這個函數把 blog 應用下的 urls.py 文件包含了進來郁惜。此外 include 前還有一個r'',這是一個空字符串甲锡。這里也可以寫其它字符串兆蕉,Django 會把這個字符串和后面 include 的 urls.py 文件中的 URL 拼接。比如說如果這里把r''改成r'blog/'缤沦,而我們在 blog.urls 中寫的 URL 是r'^$'虎韵,即一個空字符串。那么 Django 最終匹配的就是 blog/ 加上一個空字符串缸废,即 blog/包蓝。
運行結果
運行python manage.py runserver打開開發(fā)服務器,在瀏覽器輸入開發(fā)服務器的地址 http://127.0.0.1:8000/企量,可以看到 Django 返回的內容了测萎。
使用 Django 模板系統(tǒng)
這基本上就是 Django 的開發(fā)流程了,寫好處理 HTTP 請求和返回 HTTP 響應的視圖函數梁钾,然后把視圖函數綁定到相應的 URL 上绳泉。
我們看到在視圖函數里返回的是一個HttpResponse類的實例逊抡,我們給它傳入了一個希望顯示在用戶瀏覽器上的字符串姆泻。但是我們的博客不可能只顯示這么一句話零酪,它有可能會顯示很長很長的內容。比如我們發(fā)布的博客文章列表拇勃,或者一大段的博客文章四苇。不能每次都把這些大段大段的內容傳給HttpResponse。
Django 對這個問題提供了一個很好的解決方案坡垫,叫做模板系統(tǒng)蔫慧。Django 要我們把大段的文本寫到一個文件里疗韵,然后 Django 自己會去讀取這個文件,再把讀取到的內容傳給HttpResponse榆骚。讓我們用模板系統(tǒng)來改造一下上面的例子。
首先在項目根目錄(即 manage.py 文件所在目錄)下建立一個名為 templates 的文件夾煌集,用來存放模板妓肢。然后在 templates\ 目錄下建立一個名為 blog 的文件夾,用來存放和 blog 應用相關的模板苫纤。
當然模板存放在哪里是無關緊要的碉钠,只要 Django 能夠找到的就好。但是建立這樣的文件夾結構的目的是把不同應用用到的模板隔離開來卷拘,這樣方便以后維護喊废。在 templates\blog 目錄下建立一個名為 index.html 的文件,此時目錄結構應該是這樣的:
再一次強調 templates\ 目錄位于項目根目錄栗弟,而 index.html 位于 templates\blog 目錄下污筷,而不是 blog 應用下,如果弄錯了你可能會得到一個TemplateDoesNotExist 異常乍赫。如果遇到這個異常颓屑,請回來檢查一下模板目錄結構是否正確。
在 templates\blog\index.html 文件里寫入下面的代碼:
這是一個標準的 HTML 文檔耿焊,只是里面有兩個比較奇怪的地方:{{ title }}揪惦,{{ welcome }}。這是 Django 規(guī)定的語法罗侯。用 {{ }} 包起來的變量叫做模板變量器腋。Django 在渲染這個模板的時候會根據我們傳遞給模板的變量替換掉這些變量。最終在模板中顯示的將會是我們傳遞的值钩杰。
模板寫好了纫塌,還得告訴 Django 去哪里找模板,在 settings.py 文件里設置一下模板文件所在的路徑讲弄。在 settings.py 找到TEMPLATES選項措左,它的內容是這樣的:
其中DIRS就是設置模板的路徑,在 [] 中寫入os.path.join(BASE_DIR, 'templates')避除,即像下面這樣:
這里BASE_DIR是 settings.py 在配置開頭前面定義的變量怎披,記錄的是工程根目錄 blogproject\ 的值(注意是最外層的 blogproject\ 目錄)胸嘁。在這個目錄下有模板文件所在的目錄 templates\,于是利用os.path.join把這兩個路徑連起來凉逛,構成完整的模板路徑性宏,Django 就知道去這個路徑下面找模板了。
視圖函數可以改一下了:
這里不再是直接把字符串傳給HttpResponse了状飞,而是調用 Django 提供的render函數毫胜。這個函數根據我們傳入的參數來構造HttpResponse。
首先把 HTTP 請求傳了進去诬辈,然后render根據第二個參數的值 blog/index.html 找到這個模板文件并讀取模板中的內容酵使。之后render根據我們傳入的context參數的值把模板中的變量替換為我們傳遞的變量的值,{{ title }}被替換成了context字典中title對應的值焙糟,同理{{ welcome }}也被替換成相應的值凝化。
最終, HTML 模板中的內容字符串被傳遞給HttpResponse對象并返回給瀏覽器(Django 在render函數里隱式地幫我們完成了這個過程)酬荞,這樣用戶的瀏覽器上便顯示出了我們寫的 HTML 模板的內容搓劫。