Django 處理 HTTP 請(qǐng)求
Hello 視圖函數(shù)
我們先以一個(gè)最簡(jiǎn)單的 Hello World 為例來看看 django 處理上述問題的機(jī)制是怎么樣的玄柏。
綁定 URL 與視圖函數(shù)
當(dāng)用戶訪問不同的網(wǎng)址時(shí)粪摘,Django需要知道如何處理這些網(wǎng)址(路由)绍坝。django 的做法是把不同的網(wǎng)址對(duì)應(yīng)的處理函數(shù)寫在一個(gè)urls.py
文件里,當(dāng)用戶訪問某個(gè)網(wǎng)址時(shí)轩褐,django 就去會(huì)這個(gè)文件里找把介,如果找到這個(gè)網(wǎng)址蟋座,就會(huì)調(diào)用和它綁定在一起的處理函數(shù)(叫做==視圖函數(shù)==)脚牍。下面是具體的做法,首先在 blog 應(yīng)用的目錄下創(chuàng)建一個(gè) urls.py 文件莫矗,這時(shí)你的目錄看起來是這樣:
.
├── __init__.py
├── admin.py
├── apps.py
├── migrations
├── models.py
├── static
├── tests.py
├── urls.py #這個(gè)
└── views.py
urls.py
在 blog\urls.py 中寫入這些代碼:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
解釋:
- 從
django.urls
模塊中導(dǎo)入了path
函數(shù)作谚;并從當(dāng)前目錄導(dǎo)入了views
模塊。也就是上面view.py
這個(gè)文件 - 將網(wǎng)址和處理函數(shù)的關(guān)系作為參數(shù)傳給
path
函數(shù)(網(wǎng)址雀监,處理函數(shù)眨唬,處理函數(shù)的別名) - 我們本地開發(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è)空字符串昵慌,而 '' 的模式正是匹配一個(gè)空字符串,于是二者匹配已卷,django 便會(huì)調(diào)用其對(duì)應(yīng)的
views.index
函數(shù)淳蔼。
.
├── Pipfile
├── Pipfile.lock
├── blog
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
├── firstblog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── static
│ ├── tests.py
│ ├── urls.py # 修改的是這個(gè)
│ └── views.py
├── manage.py
注意在 blogproject\ 目錄下(即 settings.py 所在的目錄),原本就有一個(gè) urls.py 文件闺魏,這是整個(gè)工程項(xiàng)目的 URL 配置文件俯画。而我們這里新建了一個(gè) urls.py 文件,且位于 blog 應(yīng)用下泡仗。這個(gè)文件將用于 blog 應(yīng)用相關(guān)的 URL 配置,這樣便于模塊化管理娩怎。不要把兩個(gè)文件搞混了。
編寫視圖函數(shù)
第二步就是要實(shí)際編寫我們的 views.index 視圖函數(shù)了爬泥,按照慣例視圖函數(shù)定義在 views.py 文件里:
from django.http import HttpResponse
def index(request):
return HttpResponse("歡迎訪問我的博客首頁崩瓤!")
WEB服務(wù)器的本質(zhì)就是==接收用戶的http請(qǐng)求却桶,也就是request
,然后根據(jù)請(qǐng)求內(nèi)容返回相應(yīng)的http響應(yīng)颖系。這個(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ì)在頁面上顯示出我們傳遞的內(nèi)容 :歡迎訪問我的博客首頁栅哀!
配置項(xiàng)目 URL
前面建立了一個(gè) urls.py 文件,并且綁定了 URL 和視圖函數(shù) index留拾,還要讓Django知道去找這個(gè)urls.py
才行。django 匹配 URL 模式是在 blog\ 目錄(即 settings.py 文件所在的目錄)的 urls.py
下的沦偎,所以我們要把 firstblog 應(yīng)用下的 urls.py
文件包含到 blog\urls.py
里去,打開這個(gè)文件看到如下內(nèi)容:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('firstblog.urls')),
]
我們這里導(dǎo)入了一個(gè) include
函數(shù)搔驼,然后利用這個(gè)函數(shù)把 firstblog 應(yīng)用下的 urls.py
文件包含了進(jìn)來侈询。此外 include 前還有一個(gè) ''
,這是一個(gè)空字符串囊嘉。這里也可以寫其它字符串革为,django 會(huì)把這個(gè)字符串和后面 include
的 urls.py
文件中的 URL 拼接。比如說如果我們這里把 '' 改成 'firstblog/'焊刹,而我們?cè)?firstblog\urls.py
中寫的 URL 是 ''恳蹲,即一個(gè)空字符串。那么 django 最終匹配的就是 firstblog/ 加上一個(gè)空字符串嘉蕾,即 firstblog/。
.
├── Pipfile
├── Pipfile.lock
├── blog
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py #改的這個(gè)
│ └── wsgi.py
├── db.sqlite3
├── firstblog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── static
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
運(yùn)行結(jié)果
運(yùn)行 pipenv run python manage.py runserver
儡率,在瀏覽器輸入開發(fā)服務(wù)器的地址 http://127.0.0.1:8000/以清, 可以看到 django 返回的內(nèi)容了。
歡迎訪問我的博客首頁眉孩!
使用 django 模板系統(tǒng)
==寫好處理 HTTP 請(qǐng)求和返回 HTTP 響應(yīng)的視圖函數(shù)勒葱,然后把視圖函數(shù)綁定到相應(yīng)的 URL 上==。 這就是Django處理HTTP的流程死遭。
但我們不能每次都把大段的內(nèi)容傳給 HttpResponse凯旋。django 對(duì)這個(gè)問題給我們提供了一個(gè)很好的解決方案钉迷,叫做==模板系統(tǒng)==蜗侈。django 要我們把大段的文本寫到一個(gè)文件里,然后 django 自己會(huì)去讀取這個(gè)文件枷颊,再把讀取到的內(nèi)容傳給 HttpResponse
该面。
添加模板
首先在我們的項(xiàng)目根目錄(即 manage.py 文件所在目錄)下建立一個(gè)名為templates
的文件夾,用來存放我們的模板题造。然后在templates\
目錄下建立一個(gè)名為 blog
的文件夾猾瘸,用來存放和 blog 應(yīng)用相關(guān)的模板。在 templates\blog
目錄下建立一個(gè)名為 index.html
的文件淮悼,此時(shí)你的目錄結(jié)構(gòu)應(yīng)該是這樣的:
.
├── Pipfile
├── Pipfile.lock
├── blog
├── db.sqlite3
├── firstblog
├── manage.py
└── templates
└── blog
└── index.html
在index.html
中寫入:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ welcome }}</h1>
</body>
</html>
用 {{ }}
包起來的變量叫做==模板變量==揽思。django 在渲染這個(gè)模板的時(shí)候會(huì)根據(jù)我們傳遞給模板的變量替換掉這些變量。最終在模板中顯示的將會(huì)是我們傳遞的值羹令。
模板寫好了损痰,還得告訴 django 去哪里找模板,在 settings.py
文件里設(shè)置一下模板文件所在的路徑肪凛。在 settings.py 找到 TEMPLATES 選項(xiàng)尝丐,它的內(nèi)容是這樣的:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #修改成這樣
'APP_DIRS': True,
'OPTIONS': {
其中 DIRS
就是設(shè)置模板的路徑衡奥,在[]
中寫入 os.path.join(BASE_DIR, 'templates')
這里 BASE_DIR
是 settings.py
在配置開頭有定義矮固,記錄的是工程根目錄 查找路徑譬淳。在這個(gè)目錄下有模板文件所在的目錄 templates\
盹兢,于是利用os.path.join 把這兩個(gè)路徑連起來,構(gòu)成完整的模板路徑绎秒,django 就知道去這個(gè)路徑下面找我們的模板了见芹。視圖函數(shù)view.py
可以改成下面這樣:
from django.shortcuts import render
def index(request):
return render(request, 'blog/index.html', context={
'title': '我的博客首頁',
'welcome': '歡迎訪問我的博客首頁'
})
調(diào)用 django 提供的 render
函數(shù)。這個(gè)函數(shù)根據(jù)我們傳入的參數(shù)來構(gòu)造 HttpResponse阅懦。我們首先把 HTTP 請(qǐng)求(request)傳了進(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è)過程)搔体,這樣用戶的瀏覽器上便顯示出了我們寫的 HTML 模板的內(nèi)容了。