上篇我們介紹 URLs 時留下了 Views 的坑沒填,沒辦法,Views 作爲整個 Django 框架的核心,跟很多模板都深刻綁定在一起
本篇就來介紹這個重中之重:Views
1. 類視圖和函數視圖
之前留下了 IndexView、DetailView、ResultsView、vote 沒寫
as_view() 代表前三個是類視圖,第四個 vote 是函數視圖,視圖就是用來實現業務功能的模塊,選用類視圖還是函數視圖視情況而定,一般顯示內容的選用類視圖,實現功能的選用函數視圖, IndexView 顯示問題索引、DetailView 顯示問題內容、ResultsView 顯示投票結果,都屬於顯示內容,所以選用類視圖。vote 實現投票功能,所以選用函數視圖
2. 函數視圖
(1)通過函數名綁定 url
(2)自己編寫,第一個參數 request 是固定且必要的,第二個參數是 url 裏的參數 ( '< >' 裏包裹的)
(3)必須返回一個 HttpResponse 對象或者 Http404,404 是啥不用多說了
而對於類視圖,一般我們能使用通用視圖時,優先使用通用視圖,下面先說什麼是通用視圖
3. 通用視圖:
(1)屬於類視圖
(2)由 Django 提供 ,使用 from django.views import generic 導入
(3)類視圖自動實現了很多功能,比如自動返回 HttpResponse 對象,爲我們能節省很多代碼和精力,但我們需要學會類視圖的使用,官方鏈接:https://docs.djangoproject.com/zh-hans/2.1/topics/class-based-views/
(4)用類名綁定 url、用 model 屬性綁定數據模型, 用 template_name 屬性綁定頁面模板,從而實現對個模塊的關聯,注意每個類必須繼承通用視圖類 generic 的一個子類
4. 編寫 IndexView、DetailView、ResultsView、vote
from django.shortcuts import render # Create your views here. # 導入通用視圖 from django.views import generic # 導入要用到的數據模型 from .models import Question, Choice # 導入時區模塊 from django.utils import timezone # 導入自動生成404的快捷函數,生成HttpResponse對象的快捷函數 from django.shortcuts import get_object_or_404, render # 導入頁面重定向模塊 from django.http import HttpResponseRedirect # 導入反向解析函數 from django.urls import reverse # 創建索引視圖 # 必須繼承字generic的一個子類,這樣才能自動實現一些功能 # 類名直接對應urls.py裏path()的第二個參數 # 也就是URLs和Views是通過類名或者函數名進行區別綁定的 class IndexView(generic.ListView): # model屬性綁定數據模型 model = Question # template_name屬性綁定頁面模板 template_name = 'polls/index.html' # context_object_name 用於對傳給頁面模板的變量進行命名 context_object_name = 'question_list' # 創建問題詳情視圖 class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' # get_queryset()用於篩選model得到數據,結果返回給model def get_queryset(self): # 返回出版時間小於現在的 # Question.objects.filter(pub_date__lte=timezone.now()) # 是Django提供的數據庫API的寫法 return Question.objects.filter(pub_date__lte=timezone.now()) # 創建投票結果視圖 class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' # 創建投票功能視圖,是函數視圖,實現投票業務 def vote(request, question_id): # 獲取主鍵pk等於參數question_id的Question # get_object_or_404()實現:要麼獲取成功,要麼自動返回Http404 # 第一個參數表示要獲取的數據模型 # 第二個參數是獲取條件 question = get_object_or_404(Question, pk=question_id) try: # 獲取投票選項 # question.choice_set.get()是數據庫API的寫法 # request.POST[]以字符串形式返回選擇的Choice的ID selected_choice = question.choice_set.get(pk=request.POST['choice']) # 如果在request.POST['choice']數據中沒有提供choice,POST將引發一個KeyError except (KeyError, Choice.DoesNotExist): # 如果choice不存在引發KeyError,就返回polls/detail.html頁面 # render()用於返回HttpResponse對象 # 第一個參數request是固定且必要的 # 第二個參數是綁定的頁面模板 # 第三個參數是傳到模板中的參數,是一個字典類型 return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", }) else: # 選票加一 selected_choice.votes += 1 # 保存選票數據 selected_choice.save() # 重定向到polls:results的鏈接,參數是url # reverse()用於對url反向解析:把名字變爲鏈接 # 第一個參數是url的名字,路由urls.py裏面命名的 # 第二個參數是url的參數,是一個元組類型 return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
代碼中的一些說明:
(1)代碼中的 polls/index.html、polls/detail.html、polls/results.html 等 HTML 文件是頁面,頁面模板 Templates 將在下一篇介紹,這裏先這樣寫着,留個坑下篇填
(2)數據庫API:由Django 提供的用於訪問數據庫的接口,比如Question.objects.filter() 用於篩選,其寫法需要學習,官方文檔:https://docs.djangoproject.com/zh-hans/2.1/topics/db/queries/
(3)request.POST['choice']以字符串形式返回選擇的 Choice 的 ID。request.POST 的值永遠是字符串,如果在 request.POST['choice'] 數據中沒有提供 choice,POST 將引發一個 KeyError
(4)render() 是 Views 裏面一個常用的重要函數,通過第二個參數來關聯頁面模板,第三個參數向模板傳參,實現了Views 與 Templates 的交互
(5)重定向就是跳轉的意思,他的參數是url
(6)reverse() 是反向解析函數:解析是把 url 用它的名字代替,參見 urls,py 裏的命名空間和 name;反向解析就是把名字還原成 url,比如對於代碼中的 'polls:results' ,根據查找 urls.py 裏的路由表,可反向解析爲 '<int:pk>/results/' ,再根據參數 args=(question.id,) ,就解析成 'question.id/results/' (其中 question.id 已經是具體數字),這樣就完整地實現了從 name 到 url 的反向解析,然後就可以做作爲參數傳給重定向函數 HttpResponseRedirect( ) 了