Django框架學習 - 創(chuàng)建視圖

視圖簡介

視圖在Django中的作用是用于處理Web請求信息以及返回響應信息的函數(shù)。
當我們訪問http://127.0.0.1:8000/polls時,Django會解析出'polls'這個路徑,然后拿著這個路徑去URLconfs里配置相對應的視圖函數(shù),視圖函數(shù)接收請求,然后處理請求,最后返回響應信息,也許這一段不是很理解,但是當做完之后再回頭看,就很清楚了。

投票應用,需要列以下幾個視圖:

  • 問題索引頁——展示最近的幾個投票問題
  • 問題詳情頁——展示某個投票的問題和不帶結果的選項列表
  • 問題結果頁——展示某個投票的結果
  • 投票處理器——用于響應用戶為某個問題的特定選項投票的操作

創(chuàng)建視圖

增加視圖

我們通過編輯polls/views.py來增加三個視圖

# 創(chuàng)建問題詳情頁視圖
def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

# 創(chuàng)建問題結果頁視圖
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

# 創(chuàng)建處理器視圖
def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

其中request屬性,當一個頁面被請求時,Django就會創(chuàng)建一個包含本次請求信息的HttpRequest對象,Django會將這個對象自動傳遞給視圖函數(shù),一般約定使用request參數(shù)來接收這個對象,在視圖函數(shù)中,可以通過訪問該對象的屬性來提取http協(xié)議的的請求數(shù)據(jù),以下是常用的屬性,也可以查看【官網(wǎng)】中詳細說明

request.GET:url上攜帶的參數(shù),包含所有HTTP GET參數(shù)的類字典對象QueryDict
request.POST:post請求攜帶的數(shù)據(jù),包含所有HTTP POST參數(shù)的類字典對象QueryDict
request.method:請求方法,請求中使用的HTTP方法的字符串表示,全大寫(POST/GET)
request.path:完整路徑
request.path_info:URL的路徑 不包含ip和端口 不包含參數(shù)
request.body:請求體

配置URLconfs

我們通過上面增加了polls/views.py的內容,但是我們還不能馬上使用,因為當我們去訪問的時候,Django并不能通過URL找到對應的視圖函數(shù),所以,我要在URLconfs里增加新增視圖函數(shù)的路由,那來編輯一下polls/urls.py

from django.urls import path

from . import views

urlpatterns = [
    # 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'),
]

保存,重新運行Django。當然,我們可以根據(jù)上面路徑上的注釋來測試訪問一下,即http://127.0.0.1:8000/polls/34、http://127.0.0.1:8000/polls/34/resultshttp://127.0.0.1:8000/polls/34/vote,其實很簡單的,是視圖中question_id在接收path中的<int:question_id>,如果你不能清楚也沒關系,后續(xù)將內容添加后,可以幫助更容易的理解。

使用視圖

結合polls這個項目,我們給polls/views.py中的index視圖函數(shù)進行修改一下,利用數(shù)據(jù)庫API來查詢和展示前五個投票問題

from django.http import HttpResponse
from .models import Question


def index(request):
    # 利用數(shù)據(jù)庫API來獲取前五個問題
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    # 將內容提取出來,使用','符號拼接起來
    output = ', '.join([q.question_text for q in latest_question_list])
    # 使用HttpResponse返回拼接后的內容
    return HttpResponse(output)

創(chuàng)建靜態(tài)文件

上面的代碼可以展示前五個問題,但是這時的展示是沒有經(jīng)過渲染的,所以我們給它們加上模板文件進行渲染,Django中提供了對應的尋找目錄,即在polls下創(chuàng)建一個template文件夾,再在這個文件夾下創(chuàng)建一個polls的文件夾,最后在這個文件里創(chuàng)建index.html文件,完整的路徑就是polls/template/polls/index.html,這個是在setting.py文件中TEMPLATES選項設置的。

然后,我們可以將以下內容,填充到剛創(chuàng)建的模板文件(polls/template/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 %}

最后,我們通過修改polls/views.py來使用模板渲染

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    # 利用數(shù)據(jù)庫API來獲取前五個問題
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    # 指定渲染使用的模板
    template = loader.get_template('polls/index.html')
    # 指定問題列表
    context = {
        'latest_question_list': latest_question_list,
    }
    # 將問題列表傳到模板中,然后通過HttpResponse返回響應
    return HttpResponse(template.render(context, request))

快捷函數(shù):render()

以上代碼中,載入模板-填充模板上下文-生成HttpResponse對象,這一套流程使用太過于頻繁,所以Django提供了一個render()函數(shù)來減少冗余,我們把上面的代碼通過render()來重寫

from django.shortcuts import render
from .models import Question

def 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)

拋出404

訪問404,也是很常用的一個操作,當我們訪問不存在的一個問題ID時,就拋出404異常

from django.http import Http404
from django.shortcuts import render
from .model import Question

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

此時,這個detail視圖使用到了一個模板文件,但是我們沒有創(chuàng)建,所以現(xiàn)在無法正常運行,我們先創(chuàng)建一個,進行占位,即polls/template/polls/detail.html

{{ question }}

快捷函數(shù):get_object_or_404()

嘗試使用get()函數(shù)獲取一個對象,如果不存在就拋出Http404異常也是一個普遍的流程,對此,Django也提供了一個快捷函數(shù),所以我們利用這個快捷函數(shù)來修改一個detail視圖

from django.shortcuts import get_object_or_404, render
from .model import Question

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

優(yōu)化模板

我們來補全polls/detail.html模板文件

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

模板中通過點來訪問變量的屬性,即{{ question.question_text }}
{ % for % }循環(huán)中發(fā)生的函數(shù)調用:question.choice_set.all被解釋為Python代碼中的question.choice_set.all(),將會返回一個可迭代的Choice對象,這個對象被for循環(huán)輸出

去除硬編碼

向上翻,可以看到polls/index.html中的投票鏈接是硬鏈接

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

這個問題在于,硬鏈接和強耦合相鏈接,對于一個包含多個應用的項目,修改起來比較復雜,所以我們可以使用在polls/urls.py中為URL定義的name參數(shù)來替代原有的硬鏈接,使用{ % url %}來使用

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

URL命名空間

命名空間的作用是,區(qū)分多個應用時,{% url %}中name參數(shù)對應哪條URL,修改比較簡單,就是在polls/urls.py中添加app_name參數(shù)

from django.urls import path
from . import views

app_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'),
]

所以還需要修改一下polls/index.html文件

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容