摘要:比如說(shuō)如果我們這里把改成,而我們?cè)谥袑?xiě)的是,即一個(gè)空字符串。那么最終匹配的就是加上一個(gè)空字符串,即。在博客首頁(yè)視圖追夢(mèng)人物的博客的評(píng)論區(qū)留言。
Django 處理 HTTP 請(qǐng)求
Web 應(yīng)用的交互過(guò)程其實(shí)就是 HTTP 請(qǐng)求與響應(yīng)的過(guò)程。無(wú)論是在 PC 端還是移動(dòng)端,我們通常使用瀏覽器來(lái)上網(wǎng),上網(wǎng)流程大致來(lái)說(shuō)是這樣的:
我們打開(kāi)瀏覽器,在地址欄輸入想訪問(wèn)的網(wǎng)址,比如 http://zmrenwu.com/(當(dāng)然你也可能從收藏夾里直接打開(kāi)網(wǎng)站,但本質(zhì)上都是一樣的)。
瀏覽器知道我們想要訪問(wèn)哪個(gè)網(wǎng)址后,它在后臺(tái)幫我們做了很多事情。主要就是把我們的訪問(wèn)意圖包裝成一個(gè) HTTP 請(qǐng)求,發(fā)給我們想要訪問(wèn)的網(wǎng)址所對(duì)應(yīng)的服務(wù)器。通俗點(diǎn)說(shuō)就是瀏覽器幫我們通知網(wǎng)站的服務(wù)器,說(shuō)有人來(lái)訪問(wèn)你啦,訪問(wèn)的請(qǐng)求都寫(xiě)在 HTTP 里了,你按照要求處理后告訴我,我再幫你回應(yīng)他!
服務(wù)器處理了HTTP 請(qǐng)求,然后生成一段 HTTP 響應(yīng)給瀏覽器。瀏覽器解讀這個(gè)響應(yīng),把相關(guān)的內(nèi)容在瀏覽器里顯示出來(lái),于是我們就看到了網(wǎng)站的內(nèi)容。比如你訪問(wèn)了我的博客主頁(yè) http://zmrenwu.com/,服務(wù)器接收到這個(gè)請(qǐng)求后就知道用戶訪問(wèn)的是首頁(yè),首頁(yè)顯示的是全部文章列表,于是它從數(shù)據(jù)庫(kù)里把文章數(shù)據(jù)取出來(lái),生成一個(gè)寫(xiě)著這些數(shù)據(jù)的 HTML 文檔,包裝到 HTTP 響應(yīng)里發(fā)給瀏覽器,瀏覽器解讀這個(gè)響應(yīng),把 HTML 文檔顯示出來(lái),我們就看到了文章列表的內(nèi)容。
因此,Django 作為一個(gè) Web 框架,它的使命就是處理流程中的第二步。即接收瀏覽器發(fā)來(lái)的 HTTP 請(qǐng)求,返回相應(yīng)的 HTTP 響應(yīng)。于是引出這么幾個(gè)問(wèn)題:
Django 如何接收 HTTP 請(qǐng)求?
Django 如何處理這個(gè) HTTP 請(qǐng)求?
Django 如何生成 HTTP 響應(yīng)?
對(duì)于如何處理這些問(wèn)題,Django 有其一套規(guī)定的機(jī)制。我們按照 Django 的規(guī)定,就能開(kāi)發(fā)出所需的功能。
Hello 視圖函數(shù)我們先以一個(gè)最簡(jiǎn)單的 Hello World 為例來(lái)看看 Django 處理上述問(wèn)題的機(jī)制是怎么樣的。
綁定 URL 與視圖函數(shù)首先 Django 需要知道當(dāng)用戶訪問(wèn)不同的網(wǎng)址時(shí),應(yīng)該如何處理這些不同的網(wǎng)址(即所說(shuō)的路由)。Django 的做法是把不同的網(wǎng)址對(duì)應(yīng)的處理函數(shù)寫(xiě)在一個(gè) urls.py 文件里,當(dāng)用戶訪問(wèn)某個(gè)網(wǎng)址時(shí),Django 就去會(huì)這個(gè)文件里找,如果找到這個(gè)網(wǎng)址,就會(huì)調(diào)用和它綁定在一起的處理函數(shù)(叫做視圖函數(shù))。
下面是具體的做法,首先在 blog 應(yīng)用的目錄下創(chuàng)建一個(gè) urls.py 文件,這時(shí)你的目錄看起來(lái)是這樣:
blog __init__.py admin.py apps.py migrations 0001_initial.py __init__.py models.py tests.py views.py urls.py
在 blogurls.py 中寫(xiě)入這些代碼:
blog/urls.py from django.conf.urls import url from . import views urlpatterns = [ url(r"^$", views.index, name="index"), ]
我們首先從 django.conf.urls 導(dǎo)入了 url 函數(shù),又從當(dāng)前目錄下導(dǎo)入了 views 模塊。然后我們把網(wǎng)址和處理函數(shù)的關(guān)系寫(xiě)在了 urlpatterns 列表里。
綁定關(guān)系的寫(xiě)法是把網(wǎng)址和對(duì)應(yīng)的處理函數(shù)作為參數(shù)傳給 url 函數(shù)(第一個(gè)參數(shù)是網(wǎng)址,第二個(gè)參數(shù)是處理函數(shù)),另外我們還傳遞了另外一個(gè)參數(shù) name,這個(gè)參數(shù)的值將作為處理函數(shù) index 的別名,這在以后會(huì)用到。
注意這里我們的網(wǎng)址是用正則表達(dá)式寫(xiě)的,Django 會(huì)用這個(gè)正則表達(dá)式去匹配用戶實(shí)際輸入的網(wǎng)址,如果匹配成功,就會(huì)調(diào)用其后面的視圖函數(shù)做相應(yīng)的處理。
比如說(shuō)我們本地開(kāi)發(fā)服務(wù)器的域名是 http://127.0.0.1:8000,那么當(dāng)用戶輸入網(wǎng)址 http://127.0.0.1:8000 后,Django 首先會(huì)把協(xié)議 http、域名 127.0.0.1 和端口號(hào) 8000 去掉,此時(shí)只剩下一個(gè)空字符串,而 r"^$" 的模式正是匹配一個(gè)空字符串(這個(gè)正則表達(dá)式的意思是以空字符串開(kāi)頭且以空字符串結(jié)尾),于是二者匹配,Django 便會(huì)調(diào)用其對(duì)應(yīng)的 views.index 函數(shù)。
注意:在項(xiàng)目根目錄的 blogproject 目錄下(即 settings.py 所在的目錄),原本就有一個(gè) urls.py 文件,這是整個(gè)工程項(xiàng)目的 URL 配置文件。而我們這里新建了一個(gè) urls.py 文件,且位于 blog 應(yīng)用下。這個(gè)文件將用于 blog 應(yīng)用相關(guān)的 URL 配置。不要把兩個(gè)文件搞混了。
編寫(xiě)視圖函數(shù)第二步就是要實(shí)際編寫(xiě)我們的 views.index 視圖函數(shù)了,按照慣例視圖函數(shù)定義在 views.py 文件里:
blog/views.py from django.http import HttpResponse def index(request): return HttpResponse("歡迎訪問(wèn)我的博客首頁(yè)!")
我們前面說(shuō)過(guò),Web 服務(wù)器的作用就是接收來(lái)自用戶的 HTTP 請(qǐng)求,根據(jù)請(qǐng)求內(nèi)容作出相應(yīng)的處理,并把處理結(jié)果包裝成 HTTP 響應(yīng)返回給用戶。
這個(gè)兩行的函數(shù)體現(xiàn)了這個(gè)過(guò)程。它首先接受了一個(gè)名為 request 的參數(shù),這個(gè) request 就是 Django 為我們封裝好的 HTTP 請(qǐng)求,它是類 HttpRequest 的一個(gè)實(shí)例。然后我們便直接返回了一個(gè) HTTP 響應(yīng)給用戶,這個(gè) HTTP 響應(yīng)也是 Django 幫我們封裝好的,它是類 HttpResponse 的一個(gè)實(shí)例,只是我們給它傳了一個(gè)自定義的字符串參數(shù)。
瀏覽器接收到這個(gè)響應(yīng)后就會(huì)在頁(yè)面上顯示出我們傳遞的內(nèi)容 :歡迎訪問(wèn)我的博客首頁(yè)!
配置項(xiàng)目 URL還差最后一步了,我們前面建立了一個(gè) urls.py 文件,并且綁定了 URL 和視圖函數(shù) index,但是 Django 并不知道。Django 匹配 URL 模式是在 blogproject 目錄(即 settings.py 文件所在的目錄)的 urls.py 下的,所以我們要把 blog 應(yīng)用下的 urls.py 文件包含到 blogprojecturls.py 里去,打開(kāi)這個(gè)文件看到如下內(nèi)容:
blogproject/urls.py """ 一大段注釋 """ from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r"^admin/", admin.site.urls), ]
修改成如下的形式:
- from django.conf.urls import url + from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r"^admin/", admin.site.urls), + url(r"", include("blog.urls")), ]
這里 - 表示刪掉這一行,+ 表示添加這一行。
我們這里導(dǎo)入了一個(gè) include 函數(shù),然后利用這個(gè)函數(shù)把 blog 應(yīng)用下的 urls.py 文件包含了進(jìn)來(lái)。此外 include 前還有一個(gè) r"",這是一個(gè)空字符串。這里也可以寫(xiě)其它字符串,Django 會(huì)把這個(gè)字符串和后面 include 的 urls.py 文件中的 URL 拼接。比如說(shuō)如果我們這里把 r"" 改成 r"blog/",而我們?cè)?blog.urls 中寫(xiě)的 URL 是 r"^$",即一個(gè)空字符串。那么 Django 最終匹配的就是 blog/ 加上一個(gè)空字符串,即 blog/。
運(yùn)行結(jié)果激活虛擬環(huán)境,運(yùn)行 python manage.py runserver 打開(kāi)開(kāi)發(fā)服務(wù)器,在瀏覽器輸入開(kāi)發(fā)服務(wù)器的地址 http://127.0.0.1:8000/,可以看到 Django 返回的內(nèi)容了。
使用 Django 模板系統(tǒng)歡迎訪問(wèn)我的博客首頁(yè)!
這基本上就上 Django 的開(kāi)發(fā)流程了,寫(xiě)好處理 HTTP 請(qǐng)求和返回 HTTP 響應(yīng)的視圖函數(shù),然后把視圖函數(shù)綁定到相應(yīng)的 URL 上。
但是等一等!我們看到在視圖函數(shù)里返回的是一個(gè) HttpResponse 類的實(shí)例,我們給它傳入了一個(gè)希望顯示在用戶瀏覽器上的字符串。但是我們的博客不可能只顯示這么一句話,它有可能會(huì)顯示很長(zhǎng)很長(zhǎng)的內(nèi)容。比如我們發(fā)布的博客文章列表,或者一大段的博客文章。我們不能每次都把這些大段大段的內(nèi)容傳給 HttpResponse。
Django 對(duì)這個(gè)問(wèn)題給我們提供了一個(gè)很好的解決方案,叫做模板系統(tǒng)。Django 要我們把大段的文本寫(xiě)到一個(gè)文件里,然后 Django 自己會(huì)去讀取這個(gè)文件,再把讀取到的內(nèi)容傳給 HttpResponse。讓我們用模板系統(tǒng)來(lái)改造一下上面的例子。
首先在我們的項(xiàng)目根目錄(即 manage.py 文件所在目錄)下建立一個(gè)名為 templates 的文件夾,用來(lái)存放我們的模板。然后在 templates 目錄下建立一個(gè)名為 blog 的文件夾,用來(lái)存放和 blog 應(yīng)用相關(guān)的模板。
當(dāng)然模板存放在哪里是無(wú)關(guān)緊要的,只要 Django 能夠找到的就好。但是我們建立這樣的文件夾結(jié)構(gòu)的目的是把不同應(yīng)用用到的模板隔離開(kāi)來(lái),這樣方便以后維護(hù)。我們?cè)?templatesblog 目錄下建立一個(gè)名為 index.html 的文件,此時(shí)你的目錄結(jié)構(gòu)應(yīng)該是這樣的:
blogproject manage.py blogproject __init__.py settings.py ... blog __init__.py models.py ,,, templates blog index.html
再一次強(qiáng)調(diào) templates 目錄位于項(xiàng)目根目錄,而 index.html 位于 templatesblog 目錄下,而不是 blog 應(yīng)用下,如果弄錯(cuò)了你可能會(huì)得到一個(gè)TemplateDoesNotExist 異常。如果遇到這個(gè)異常,請(qǐng)回來(lái)檢查一下模板目錄結(jié)構(gòu)是否正確。
在 templatesblogindex.html 文件里寫(xiě)入下面的代碼:
{{ title }} {{ welcome }}
這是一個(gè)標(biāo)準(zhǔn)的 HTML 文檔,只是里面有兩個(gè)比較奇怪的地方:{{ title }},{{ welcome }}。這是 Django 規(guī)定的語(yǔ)法。用 {{ }} 包起來(lái)的變量叫做模板變量。Django 在渲染這個(gè)模板的時(shí)候會(huì)根據(jù)我們傳遞給模板的變量替換掉這些變量。最終在模板中顯示的將會(huì)是我們傳遞的值。
注意:index.html 必須以 UTF-8 的編碼格式保存,且小心不要往里面添加一些特殊字符,否則極有可能得到一個(gè) UnicodeDecodeError 這樣的錯(cuò)誤。
模板寫(xiě)好了,還得告訴 Django 去哪里找模板,在 settings.py 文件里設(shè)置一下模板文件所在的路徑。在 settings.py 找到 TEMPLATES 選項(xiàng),它的內(nèi)容是這樣的:
blogproject/settings.py TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ]
其中 DIRS 就是設(shè)置模板的路徑,在 [] 中寫(xiě)入 os.path.join(BASE_DIR, "templates"),即像下面這樣:
blogproject/settings.py TEMPLATES = [ { ... "DIRS": [os.path.join(BASE_DIR, "templates")], ... }, ]
這里 BASE_DIR 是 settings.py 在配置開(kāi)頭前面定義的變量,記錄的是工程根目錄 blogproject 的值(注意是最外層的 blogproject 目錄)。在這個(gè)目錄下有模板文件所在的目錄 templates,于是利用os.path.join 把這兩個(gè)路徑連起來(lái),構(gòu)成完整的模板路徑,Django 就知道去這個(gè)路徑下面找我們的模板了。
視圖函數(shù)可以改一下了:
blog/views.py from django.http import HttpResponse from django.shortcuts import render def index(request): return render(request, "blog/index.html", context={ "title": "我的博客首頁(yè)", "welcome": "歡迎訪問(wèn)我的博客首頁(yè)" })
這里我們不再是直接把字符串傳給 HttpResponse 了,而是調(diào)用 Django 提供的 render 函數(shù)。這個(gè)函數(shù)根據(jù)我們傳入的參數(shù)來(lái)構(gòu)造 HttpResponse。
我們首先把 HTTP 請(qǐng)求傳了進(jìn)去,然后 render 根據(jù)第二個(gè)參數(shù)的值 blog/index.html 找到這個(gè)模板文件并讀取模板中的內(nèi)容。之后 render 根據(jù)我們傳入的 context 參數(shù)的值把模板中的變量替換為我們傳遞的變量的值,{{ title }} 被替換成了 context 字典中 title 對(duì)應(yīng)的值,同理 {{ welcome }} 也被替換成相應(yīng)的值。
最終,我們的 HTML 模板中的內(nèi)容字符串被傳遞給 HttpResponse 對(duì)象并返回給瀏覽器(Django 在 render 函數(shù)里隱式地幫我們完成了這個(gè)過(guò)程),這樣用戶的瀏覽器上便顯示出了我們寫(xiě)的 HTML 模板的內(nèi)容。
總結(jié)本章節(jié)的代碼位于:Step5: blog index view。
如果遇到問(wèn)題,請(qǐng)通過(guò)下面的方式尋求幫助。
在 Django 博客首頁(yè)視圖 - 追夢(mèng)人物的博客 的評(píng)論區(qū)留言。
將問(wèn)題的詳細(xì)描述通過(guò)郵件發(fā)送到 [email protected],一般會(huì)在 24 小時(shí)內(nèi)回復(fù)。
更多Django 教程,請(qǐng)?jiān)L問(wèn) 追夢(mèng)人物的博客。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44400.html
摘要:在此之前我們已經(jīng)編寫(xiě)了的首頁(yè)視圖,并且配置了和模板,讓能夠正確地處理請(qǐng)求并返回合適的響應(yīng)。正確引入了靜態(tài)文件后樣式顯示正常了。在真正的博客首頁(yè)視圖追夢(mèng)人物的博客的評(píng)論區(qū)留言。更多教程,請(qǐng)?jiān)L問(wèn)追夢(mèng)人物的博客。 在此之前我們已經(jīng)編寫(xiě)了 Blog 的首頁(yè)視圖,并且配置了 URL 和模板,讓 Django 能夠正確地處理 HTTP 請(qǐng)求并返回合適的 HTTP 響應(yīng)。不過(guò)我們僅僅在首頁(yè)返回了一句...
摘要:本節(jié)接上周的文檔學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)第一周教程編寫(xiě)博客的首頁(yè)面,我們繼續(xù)給博客添加功能,以及改善前面不合理的部分。返回該視圖要顯示的對(duì)象。目前小組正在完成第一個(gè)項(xiàng)目,本文即是該項(xiàng)目第二周的相關(guān)文檔。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門(mén)教程。 上周我們完成了博客的 Model 部分,以及 Blog 的首頁(yè)視圖 IndexView。 本節(jié)接上周的文檔 Djan...
摘要:學(xué)習(xí)小組是由我發(fā)起的一個(gè)促進(jìn)新手互相學(xué)習(xí)互相幫助的組織。當(dāng)然如果你不喜歡英文,可以看我們的中文翻譯版本入門(mén)教程中文翻譯版。如果模板文件中有如下代碼那么渲染時(shí)就會(huì)循環(huán)渲染篇文章,并且也會(huì)被存儲(chǔ)在數(shù)據(jù)庫(kù)中文章的標(biāo)題取代。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門(mén)教程。 本節(jié)是 Django Blog 項(xiàng)目的開(kāi)篇,是?Django 學(xué)習(xí)小組的集體學(xué)習(xí)成果。Django...
摘要:對(duì)文章詳情視圖而言,每篇文章對(duì)應(yīng)著不同的。在博客文章詳情頁(yè)追夢(mèng)人物的博客的評(píng)論區(qū)留言。將問(wèn)題的詳細(xì)描述通過(guò)郵件發(fā)送到,一般會(huì)在小時(shí)內(nèi)回復(fù)。更多教程,請(qǐng)?jiān)L問(wèn)追夢(mèng)人物的博客。 首頁(yè)展示的是所有文章的列表,當(dāng)用戶看到感興趣的文章時(shí),他點(diǎn)擊文章的標(biāo)題或者繼續(xù)閱讀的按鈕,應(yīng)該跳轉(zhuǎn)到文章的詳情頁(yè)面來(lái)閱讀文章的詳細(xì)內(nèi)容?,F(xiàn)在讓我們來(lái)開(kāi)發(fā)博客的詳情頁(yè)面,有了前面的基礎(chǔ),開(kāi)發(fā)流程都是一樣的了:首先配置 ...
摘要:聲明本渣渣部分代碼參考自其實(shí)有很多代碼是不需要自己一行行碼出來(lái),生產(chǎn)力是第一位。只有研究型人才需要生產(chǎn)代碼,作為一名渣渣拿來(lái)用是最高效的做法。程序員都有一個(gè)開(kāi)源的精神,碼出來(lái)的代碼本身是希望更多的人用到,應(yīng)用到生產(chǎn)中。 聲明:本渣渣部分代碼參考自TendCode其實(shí)有很多代碼是不需要自己一行行碼出來(lái),生產(chǎn)力是第一位。只有研究型人才需要生產(chǎn)代碼,作為一名渣渣拿來(lái)用是最高效的做法。程序員都...
閱讀 1668·2021-09-02 09:55
閱讀 1151·2019-08-30 13:19
閱讀 1420·2019-08-26 13:51
閱讀 1474·2019-08-26 13:49
閱讀 2420·2019-08-26 12:13
閱讀 480·2019-08-26 11:52
閱讀 1932·2019-08-26 10:58
閱讀 3110·2019-08-26 10:19