Django項(xiàng)目怎么實(shí)現(xiàn)視圖和模板-創(chuàng)新互聯(lián)

創(chuàng)新互聯(lián)www.cdcxhl.cn八線(xiàn)動(dòng)態(tài)BGP香港云服務(wù)器提供商,新人活動(dòng)買(mǎi)多久送多久,劃算不套路!

企業(yè)建站必須是能夠以充分展現(xiàn)企業(yè)形象為主要目的,是企業(yè)文化與產(chǎn)品對(duì)外擴(kuò)展宣傳的重要窗口,一個(gè)合格的網(wǎng)站不僅僅能為公司帶來(lái)巨大的互聯(lián)網(wǎng)上的收集和信息發(fā)布平臺(tái),成都創(chuàng)新互聯(lián)公司面向各種領(lǐng)域:成都發(fā)電機(jī)維修網(wǎng)站設(shè)計(jì)、成都營(yíng)銷(xiāo)網(wǎng)站建設(shè)解決方案、網(wǎng)站設(shè)計(jì)等建站排名服務(wù)。

Django項(xiàng)目怎么實(shí)現(xiàn)視圖和模板?針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

一、概述

一個(gè)視圖就是一個(gè)頁(yè)面,通常提供特定的功能,使用特定的模板。例如:在一個(gè)博客應(yīng)用中,你可能會(huì)看到下列視圖:

博客主頁(yè):顯示最新發(fā)布的一些內(nèi)容每篇博客的詳細(xì)頁(yè)面:博客的永久鏈接基于年的博客頁(yè)面:顯示指定年內(nèi)的所有博客文章基于月的博客頁(yè)面:顯示指定月內(nèi)的所有博客文章基于天的博客頁(yè)面:顯示指定日內(nèi)的所有博客文章發(fā)布評(píng)論:處理針對(duì)某篇博客發(fā)布的評(píng)論

在我們的投票應(yīng)用中,我們將建立下面的視圖:

問(wèn)卷“index”頁(yè):顯示最新的一些問(wèn)卷問(wèn)卷“detail”頁(yè)面:顯示一個(gè)問(wèn)卷的詳細(xì)文本內(nèi)容,沒(méi)有調(diào)查結(jié)果但是有一個(gè)投票或調(diào)查表單。問(wèn)卷“results”頁(yè)面:顯示某個(gè)問(wèn)卷的投票或調(diào)查結(jié)果。投票動(dòng)作頁(yè)面:處理針對(duì)某個(gè)問(wèn)卷的某個(gè)選項(xiàng)的投票動(dòng)作。

在Django中,網(wǎng)頁(yè)和其它的一些內(nèi)容都是通過(guò)視圖來(lái)處理的。視圖其實(shí)就是一個(gè)簡(jiǎn)單的Python函數(shù)(在基于類(lèi)的視圖中稱(chēng)為方法)。Django通過(guò)對(duì)比請(qǐng)求的URL地址來(lái)選擇對(duì)應(yīng)的視圖。

在你上網(wǎng)的過(guò)程中,很可能看見(jiàn)過(guò)像這樣的 URL: "ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B" 。別擔(dān)心,Django 里的 URL規(guī)則要比這優(yōu)雅的多!

一個(gè) URL 模式定義了一種 URL 的基本格式,比如:/newsarchive/<year>/<month>/。

為了將 URL 和視圖關(guān)聯(lián)起來(lái),Django 使用了 'URLconfs' 來(lái)配置。URLconf 將 URL 模式映射到視圖。

二、編寫(xiě)視圖

下面,打開(kāi)polls/views.py文件,輸入下列代碼:

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

然后,在polls/urls.py文件中加入下面的url模式,將其映射到我們上面新增的視圖。

from django.urls import pathfrom . import viewsurlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),]

現(xiàn)在去瀏覽器中訪問(wèn)/polls/34/(注意:這里省略了域名。另外,使用了二級(jí)路由后,url中都要添加字符串polls前綴,參考前面的章節(jié)),它將調(diào)用detail()函數(shù),然后在頁(yè)面中顯示你在url里提供的ID。訪問(wèn)/polls/34/results/和/polls/34/vote/,將分別顯示預(yù)定義的偽結(jié)果和投票頁(yè)面。(PS:這里就不貼圖了,請(qǐng)大家務(wù)必自己動(dòng)手測(cè)試,多實(shí)踐。)

上面訪問(wèn)的路由過(guò)程如下:當(dāng)有人訪問(wèn)/polls/34/地址時(shí),Django將首先加載mysite.urls模塊,因?yàn)樗莝ettings文件里設(shè)置的根URL配置文件。在該文件里,Django發(fā)現(xiàn)了urlpatterns變量,于是在其內(nèi)按順序進(jìn)行匹配。當(dāng)它匹配上了polls/,就裁去url中匹配的文本polls/,然后將剩下的文本“34/”,傳遞給polls.urls進(jìn)行下一步的處理。在polls.urls中,又匹配到了<int:question_id>/,最終結(jié)果就是調(diào)用該模式對(duì)應(yīng)的detail()視圖,也就是下面的函數(shù):

detail(request=<HttpRequest object>, question_id=34)

函數(shù)中的question_id=’34’參數(shù),是由<int:question_id>/而來(lái)。使用尖括號(hào)“捕獲”這部分 URL,且以關(guān)鍵字參數(shù)的形式發(fā)送給視圖函數(shù)。上述字符串的question_id部分定義了將被用于區(qū)分匹配模式的變量名,而int則是一個(gè)轉(zhuǎn)換器決定了應(yīng)該以什么變量類(lèi)型匹配這部分的 URL 路徑。

沒(méi)必要書(shū)寫(xiě)一個(gè)如下的較為愚蠢的包含.html的模式,它顯然是沒(méi)必要,不夠簡(jiǎn)練的:

path('polls/latest.html', views.index),

三、編寫(xiě)能實(shí)際干點(diǎn)活的視圖

每個(gè)視圖至少做兩件事之一:返回一個(gè)包含請(qǐng)求頁(yè)面的HttpResponse對(duì)象或者彈出一個(gè)類(lèi)似Http404的異常。其它的則隨你便,你愛(ài)干嘛干嘛。

下面是一個(gè)新的index()視圖,用于替代先前無(wú)用的index,它會(huì)根據(jù)發(fā)布日期顯示最近的5個(gè)投票問(wèn)卷。

from django.http import HttpResponsefrom .models import Questiondef index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)# Leave the rest of the views (detail, results, vote) unchanged
    # 省略了那些沒(méi)改動(dòng)過(guò)的視圖(detail, results, vote)

這里有個(gè)非常重要的問(wèn)題:在當(dāng)前視圖中的HTML頁(yè)面是硬編碼的。如果你想改變頁(yè)面的顯示內(nèi)容,就必須修改這里的Python代碼。為了解決這個(gè)問(wèn)題,需要使用Django提供的模板系統(tǒng),解耦視圖和模板之間的硬連接。

首先,在polls目錄下創(chuàng)建一個(gè)新的templates目錄,Django會(huì)在它里面查找模板文件。

項(xiàng)目的 TEMPLATES配置項(xiàng)描述了 Django 如何載入和渲染模板。默認(rèn)的設(shè)置文件設(shè)置了 DjangoTemplates 后端,并將 APP_DIRS設(shè)置成了 True。這一選項(xiàng)將會(huì)讓 DjangoTemplates 在每個(gè) INSTALLED_APPS 文件夾中尋找 "templates" 子目錄。這就是為什么盡管我們沒(méi)有像在第二部分中那樣修改 DIRS 設(shè)置,Django 也能正確找到 polls 的模板位置的原因。

在templates目錄中,再創(chuàng)建一個(gè)新的子目錄名叫polls,進(jìn)入該子目錄,創(chuàng)建一個(gè)新的html文件index.html。換句話(huà)說(shuō),你的模板文件應(yīng)該是polls/templates/polls/index.html。因?yàn)?Django 會(huì)尋找到對(duì)應(yīng)的app_directories ,所以你只需要使用polls/index.html就可以引用到這一模板了。

模板命名空間:

你也許會(huì)想,為什么不把模板文件直接放在polls/templates目錄下,而是費(fèi)勁的再建個(gè)子目錄polls呢?設(shè)想這么個(gè)情況,有另外一個(gè)app,它也有一個(gè)名叫index.html的文件,當(dāng)Django在搜索模板時(shí),有可能就找到它,然后退出搜索,這就命中了錯(cuò)誤的目標(biāo),不是我們想要的結(jié)果。解決這個(gè)問(wèn)題的最好辦法就是在templates目錄下再建立一個(gè)與app同名的子目錄,將自己所屬的模板都放到里面,從而達(dá)到獨(dú)立命名空間的作用,不會(huì)再出現(xiàn)引用錯(cuò)誤。

現(xiàn)在,將下列代碼寫(xiě)入文件polls/templates/polls/index.html:

{% if latest_question_list %}    <ul>
    {% for question in latest_question_list %}        
    <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}    </ul>{% else %}    <p>No polls are available.</p>{% endif %}

同時(shí),修改視圖文件polls/views.py,讓新的index.html文件生效:

from django.http import HttpResponse
from django.template import loader
from .models import Questiondef index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

上面的代碼會(huì)加載polls/index.html文件,并傳遞給它一個(gè)參數(shù)。這個(gè)參數(shù)是一個(gè)字典,包含了模板變量名和Python對(duì)象之間的映射關(guān)系。

在瀏覽器中通過(guò)訪問(wèn)/polls/,你可以看到一個(gè)列表,包含“What’s up”的問(wèn)卷,以及連接到其對(duì)應(yīng)詳細(xì)內(nèi)容頁(yè)面的鏈接點(diǎn)。

注意:如果你顯示的是No polls are available.說(shuō)明你前面沒(méi)有添加Questions對(duì)象。前面的大量手動(dòng)API操作你沒(méi)有做。沒(méi)關(guān)系,我們?cè)赼dmin中追加對(duì)象就可以。

快捷方式:render()

在實(shí)際運(yùn)用中,加載模板、傳遞參數(shù),返回HttpResponse對(duì)象是一整套再常用不過(guò)的操作了,為了節(jié)省力氣,Django提供了一個(gè)快捷方式:render函數(shù),一步到位!

修改成下面的代碼:

from django.shortcuts import render
from .models import Questiondef index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

注意,我們不再需要導(dǎo)入 loader和 HttpResponse,而是從django.shortcuts導(dǎo)入了render。

render()函數(shù)的第一個(gè)位置參數(shù)是請(qǐng)求對(duì)象(就是view函數(shù)的第一個(gè)參數(shù)),第二個(gè)位置參數(shù)是模板。還可以有一個(gè)可選的第三參數(shù),一個(gè)字典,包含需要傳遞給模板的數(shù)據(jù)。最后render函數(shù)返回一個(gè)經(jīng)過(guò)字典數(shù)據(jù)渲染過(guò)的模板封裝而成的HttpResponse對(duì)象。

四、返回404錯(cuò)誤

現(xiàn)在讓我們來(lái)編寫(xiě)返回具體問(wèn)卷文本內(nèi)容的視圖:

from django.http import Http404
from django.shortcuts import render
from .models import Question
# ...def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

這里有個(gè)新知識(shí)點(diǎn),如果請(qǐng)求的問(wèn)卷ID不存在,那么會(huì)彈出一個(gè)Http404錯(cuò)誤。

如果你想試試上面這段代碼是否正常工作的話(huà),你可以新建polls/detail.html文件,暫時(shí)寫(xiě)入下面的代碼:

{{ question }}

快捷方式:get_object_or_404()

就像render函數(shù)一樣,Django同樣為你提供了一個(gè)偷懶的方式,替代上面的多行代碼,那就是get_object_or_404()方法,參考下面的代碼:

from django.shortcuts import get_object_or_404, render
from .models import Question
# ...def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

別說(shuō)我沒(méi)提醒你,和render一樣,也需要從Django內(nèi)置的快捷方式模塊中導(dǎo)出get_object_or_404()!

get_object_or_404()方法將一個(gè)Django模型作為第一個(gè)位置參數(shù),后面可以跟上任意個(gè)數(shù)的關(guān)鍵字參數(shù),如果對(duì)象不存在則彈出Http404錯(cuò)誤。

同樣,還有一個(gè)get_list_or_404()方法,和上面的get_object_or_404()類(lèi)似,只不過(guò)是用來(lái)替代filter()函數(shù),當(dāng)查詢(xún)列表為空時(shí)彈出404錯(cuò)誤。(filter是模型API中用來(lái)過(guò)濾查詢(xún)結(jié)果的函數(shù),它的結(jié)果是一個(gè)列表集。而get則是查詢(xún)一個(gè)結(jié)果的方法,和filter是一個(gè)和多個(gè)的區(qū)別?。?/p>

為什么我們使用輔助函數(shù)get_object_or_404()而不是自己捕獲ObjectDoesNotExist異常呢?還有,為什么模型 API 不直接拋出ObjectDoesNotExist而是拋出 Http404呢?因?yàn)檫@樣做會(huì)增加模型層和視圖層的耦合性。指導(dǎo) Django 設(shè)計(jì)的最重要的思想之一就是要保證松散耦合。一些受控的耦合將會(huì)被包含在 django.shortcuts 模塊中。

五、 使用模板系統(tǒng)

回過(guò)頭去看看我們的 detail() 視圖。它向模板傳遞了上下文變量 question 。下面是 polls/detail.html 模板里正式的代碼:

<h2>{{ question.question_text }}</h2><ul>{% for choice in question.choice_set.all %}    
<li>{{ choice.choice_text }}</li>{% endfor %}</ul>

在模板系統(tǒng)中圓點(diǎn).是萬(wàn)能的魔法師,你可以用它訪問(wèn)對(duì)象的屬性。在例子{{ question.question_text }}中,DJango首先會(huì)在question對(duì)象中嘗試查找一個(gè)字典,如果失敗,則嘗試查找屬性,如果再失敗,則嘗試作為列表的索引進(jìn)行查詢(xún)。

在 {% for %}循環(huán)中的方法調(diào)用——question.choice_set.all其實(shí)就是Python的代碼question.choice_set.all(),它將返回一組可迭代的Choice對(duì)象,并用在{% for %}標(biāo)簽中。

這里我們對(duì)Django模板語(yǔ)言有個(gè)簡(jiǎn)單的印象就好,更深入的介紹放在后面。

六、刪除模板中硬編碼的URLs

在polls/index.html文件中,還有一部分硬編碼存在,也就是href里的“/polls/”部分:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

它對(duì)于代碼修改非常不利。設(shè)想如果你在urls.py文件里修改了路由表達(dá)式,那么你所有的模板中對(duì)這個(gè)url的引用都需要修改,這是無(wú)法接受的!

我們前面給urls定義了一個(gè)name別名,可以用它來(lái)解決這個(gè)問(wèn)題。具體代碼如下:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
Django會(huì)在polls.urls文件中查找name='detail'的url,具體的就是下面這行:
path('<int:question_id>/', views.detail, name='detail'),

舉個(gè)栗子,如果你想將polls的detail視圖的URL更換為polls/specifics/12/,那么你不需要在模板中重新修改url地址了,僅僅只需要在polls/urls.py文件中,將對(duì)應(yīng)的正則表達(dá)式改成下面這樣的就行了,所有模板中對(duì)它的引用都會(huì)自動(dòng)修改成新的鏈接:

# 添加新的單詞'specifics'

path('specifics/<int:question_id>/', views.detail, name='detail'),

七、URL names的命名空間

本教程例子中,只有一個(gè)app也就是polls,但是在現(xiàn)實(shí)中很顯然會(huì)有5個(gè)、10個(gè)、更多的app同時(shí)存在一個(gè)項(xiàng)目中。Django是如何區(qū)分這些app之間的URL name呢?

答案是使用URLconf的命名空間。在polls/urls.py文件的開(kāi)頭部分,添加一個(gè)app_name的變量來(lái)指定該應(yīng)用的命名空間:

from django.urls import pathfrom . import viewsapp_name = 'polls'urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),]

現(xiàn)在,讓我們將代碼修改得更嚴(yán)謹(jǐn)一點(diǎn),將polls/templates/polls/index.html中的

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

修改為:

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

關(guān)于Django項(xiàng)目怎么實(shí)現(xiàn)視圖和模板問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

分享名稱(chēng):Django項(xiàng)目怎么實(shí)現(xiàn)視圖和模板-創(chuàng)新互聯(lián)
瀏覽地址:http://muchs.cn/article32/dgiosc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作微信小程序、網(wǎng)站維護(hù)、網(wǎng)站策劃靜態(tài)網(wǎng)站、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司