django就是有MTV
原來(lái)的控制的C由框架自己搞定了,
M就是Model,寫(xiě)的是業(yè)務(wù)對(duì)象和數(shù)據(jù)庫(kù)的關(guān)系,從數(shù)據(jù)庫(kù)讀取數(shù)據(jù),給視圖View獲取和返回?cái)?shù)據(jù)
T是模板,給用戶展示內(nèi)容
V和T是展示哪些數(shù)據(jù)和模板怎么展現(xiàn)兩部分
以要增加書(shū)籍為例
首先在T上,要有一個(gè)html寫(xiě)這個(gè)

這個(gè)里面有一個(gè)url 'lib:addBook2'對(duì)應(yīng)的是addBook2,要在url.py里和View連起來(lái) ,url.py里有path('addBook5/',views.addBook,name='addBook2'),
MVC
在說(shuō) MTV 模式之前,讓我們來(lái)簡(jiǎn)單的說(shuō)說(shuō)著名的 MVC 模式。
MVC,是模型(Model)-視圖(View)-控制器(Controller)的縮寫(xiě)。其具體定義如下:
- M:模型(Model),數(shù)據(jù)存取層,負(fù)責(zé)業(yè)務(wù)對(duì)象和數(shù)據(jù)庫(kù)對(duì)象。
- V:視圖(View),與用戶的交互,負(fù)責(zé)顯示與怎樣顯示。
- C:控制器(Controller),接受用戶動(dòng)作,調(diào)用模型,輸出相應(yīng)視圖。
三者以一種插件似的,松耦合的方式連接在一起。

MTV
Django 的 MTV 設(shè)計(jì)模式是借鑒和遵循 MVC 的。
MTV 具體定義如下:
- M:模型(Model),負(fù)責(zé)業(yè)務(wù)對(duì)象和數(shù)據(jù)庫(kù)的關(guān)系映射。
- T:模板(Template),負(fù)責(zé)如何把頁(yè)面展示給用戶。
- V:視圖(View),負(fù)責(zé)業(yè)務(wù)邏輯,并在適當(dāng)時(shí)候調(diào)用模型和模板。
URL 分發(fā)器
URL 分發(fā)器的作用是將頁(yè)面請(qǐng)求分發(fā)給不同的視圖(View)處理,視圖再調(diào)用相應(yīng)的模型(Model)和模板(Template)。
Django Web 框架:

一個(gè)誤區(qū)是把 MVC 模式與 MTV 模式等價(jià)替換。其實(shí)這樣是不對(duì)的。
在 MTV 模式中,MVC 中的 View 分成了視圖 View(展現(xiàn)哪些數(shù)據(jù))和模板 Template(如何展現(xiàn))2 個(gè)部分,而控制器(Controller)這個(gè)要素由框架自己來(lái)實(shí)現(xiàn)了,我們需要做的就是把 URL 對(duì)應(yīng)到視圖 V 就可以了,通過(guò)這樣的 URL 配置,系統(tǒng)將一個(gè)請(qǐng)求發(fā)送到一個(gè)合適的視圖。
設(shè)計(jì)表單
在上一個(gè)實(shí)驗(yàn)中的 myApp/templates/myApp/detail.html 里,添加一個(gè)表單。
<form action="" method="post" name="addBook">
{% csrf_token %}
<p><span>書(shū)名:</span><input type="text" name="name" /></p>
<p><span>作者:</span><input type="text" name="author" /></p>
<p><span>出版社:</span><input type="text" name="pub_house" /></p>
<input type="submit" value="添加" />
</form>
簡(jiǎn)要說(shuō)明:
- 上面的模板是輸入相應(yīng)的書(shū)名、作者和出版社后,點(diǎn)擊添加,將數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)并刷新頁(yè)面顯示出來(lái)。
- 我們?cè)O(shè)置表單的
action="/addBook/",并設(shè)置method="post"。使用method="post"(與其相對(duì)的是method="get")是非常重要的,因?yàn)檫@個(gè)提交表單的行為會(huì)改變服務(wù)器端的數(shù)據(jù),無(wú)論何時(shí),當(dāng)你需要?jiǎng)?chuàng)建一個(gè)改變服務(wù)器端數(shù)據(jù)的表單時(shí),請(qǐng)使用method="post"。這不是 Django 的特定技巧,這是優(yōu)秀的網(wǎng)站開(kāi)發(fā)技巧。 - 由于我們創(chuàng)建一個(gè) POST 表單(它具有修改數(shù)據(jù)的作用),所以我們需要小心跨站點(diǎn)請(qǐng)求偽造。 但你不必太過(guò)擔(dān)心,因?yàn)?Django 已經(jīng)擁有一個(gè)用來(lái)防御它的非常容易使用的系統(tǒng)。 簡(jiǎn)而言之,所有針對(duì)內(nèi)部 URL 的 POST 表單都應(yīng)該使用
{% csrf_token %}模板標(biāo)簽。
命名空間:
教程項(xiàng)目只有一個(gè)應(yīng)用 myApp。在一個(gè)真實(shí)的 Django 項(xiàng)目中,可能會(huì)有五個(gè),十個(gè),二十個(gè),甚至更多應(yīng)用。Django 如何分辨重名的 URL 呢?
舉個(gè)例子,myApp 應(yīng)用有 detail 視圖,可能另一個(gè)博客應(yīng)用也有同名的視圖。Django 如何知道 action="" 標(biāo)簽到底對(duì)應(yīng)哪一個(gè)應(yīng)用的 URL 呢?
答案是:在根 URLconf 中添加命名空間。在 myProject/urls.py 文件中稍作修改,加上 app_name 設(shè)置命名空間:
from django.contrib import admin
from django.urls import path
from myApp import views
app_name = 'myApp' # 添加這一行
urlpatterns = [
# path('admin/', admin.site.urls),
path('', views.detail, name='detail'),
path('addBook/', views.addBook, name='addBook'),
]
現(xiàn)在回到 myApp/templates/myApp/detail.html 更改 action:
<form action="/addBook/" method="post" name="addBook"></form>
添加書(shū)籍
創(chuàng)建 addBook 函數(shù)來(lái)實(shí)現(xiàn)我們添加書(shū)籍的功能。
將下面的代碼添加到 myApp/views.py:
# myApp/views.py
from django.http import HttpResponseRedirect
from django.urls import reverse
def addBook(request):
if request.method == 'POST':
temp_name = request.POST['name']
temp_author = request.POST['author']
temp_pub_house = request.POST['pub_house']
from django.utils import timezone
temp_book = Book(name=temp_name, author=temp_author, pub_house=temp_pub_house, pub_date=timezone.now())
temp_book.save()
# 重定向
return HttpResponseRedirect(reverse('detail'))
在 myProject/urls.py 里添加 URL 地址映射:
# myProject/urls.py
path('addBook/', views.addBook, name='addBook'),
簡(jiǎn)單說(shuō)明:
-
request.POST是一個(gè)類字典對(duì)象,可以通過(guò)關(guān)鍵字的名字獲取提交的數(shù)據(jù)。 這個(gè)例子中,request.POST['name']以字符串形式返回name的值。request.POST的值永遠(yuǎn)是字符串。 - 在添加書(shū)籍之后,代碼返回一個(gè)
HttpResponseRedirect而不是常用的HttpResponse,HttpResponseRedirect只接收一個(gè)參數(shù):用戶將要被重定向的 URL。 - 你應(yīng)該在每次處理 POST 數(shù)據(jù)時(shí),都返回
HttpResponseRedirect。這也不是 Django 的特定技巧,這是優(yōu)秀的網(wǎng)站開(kāi)發(fā)的實(shí)踐。 - 在這個(gè)例子中,我們?cè)?
HttpResponseRedirect的構(gòu)造函數(shù)中使用reverse()函數(shù)。這個(gè)函數(shù)避免了我們?cè)谝晥D函數(shù)中硬編碼 URL。它需要我們給出想要跳轉(zhuǎn)的視圖的名字和該視圖所對(duì)應(yīng)的 URL 模式中需要給該視圖提供的參數(shù)。reverse()調(diào)用后將返回這樣一個(gè)字符串:/detail/。
添加書(shū)籍功能完成,現(xiàn)在可以隨意添加書(shū)籍。
打開(kāi) Web 服務(wù)訪問(wèn)鏈接就可以查看效果:
添加前:
添加后:
刪除書(shū)籍
刪除書(shū)籍功能實(shí)現(xiàn)起來(lái)也很簡(jiǎn)單。
首先,在 myApp/detail.html 中設(shè)計(jì)我們的模板。
{% for book in book_list.all %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.pub_house }}</td>
<td>{{ book.pub_date }}</td>
<td><a href="{% url 'delBook' book.id %}">刪除</a></td><!--只添加這一行-->
</tr>
{% endfor %}
</table>
可以看出,只需要在每個(gè)書(shū)籍后面添加一個(gè)刪除的按鈕。刪除時(shí)也傳遞了需要?jiǎng)h除的圖書(shū)的 id。
接著,配置 url,只需在 myProject/urls.py 中添加這一行:
# myProject/urls.py
path('delBook/<int:book_id>', views.deleteBook, name='delBook'),
這里 <int:book_id> 是接收傳遞的參數(shù) book_id。
最后設(shè)計(jì)視圖函數(shù):
# myApp/views.py
def deleteBook(request, book_id):
bookID = book_id
Book.objects.filter(id=bookID).delete()
# 重定向
return HttpResponseRedirect(reverse('detail'))
這個(gè)視圖中,獲取到 book 的 id,根據(jù) id 來(lái)刪除指定書(shū)籍。最后跟上面的添加書(shū)籍函數(shù)相同,使用重定位刷新頁(yè)面。
打開(kāi) Web 服務(wù)訪問(wèn)鏈接查看效果:
刪除后:
學(xué)習(xí)資料來(lái)自實(shí)驗(yàn)樓