回上方

視圖、網址、範本

使用者透過瀏覽器存取 Django 專案網站服務時,大致流程如下圖:



我們要建立第一個網頁,開啟 poll/default/urls.py ,修改為以下程式碼。

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('default.urls')), ]

投票主題列表

網址

新增檔案 poll/default/urls.py ,定義 default 的路徑規則。

from django.urls import path from . import views urlpatterns = [ path('poll/', views.PollList.as_view()), ]

視圖

開啟 poll/default/views.py ,修改為以下程式碼。

from django.shortcuts import render from django.views.generic import ListView from .models import * # Create your views here. # 投票主題列表 class PollList(ListView): model = Poll

範本

:bulb: 頁面範本要放在哪裡?

在專案的 settings.py 設定檔中有一段關於頁面範本處理的設定值:

TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]

建立目錄 poll/default/templates/default

為了維持整個網站頁面間外觀的一致性,先新增網站頁面範本檔案 poll/default/templates/base.html

<!DOCTYPE html> <html lang="zh-hant"> <head> </head> <body> <div id="main-content"> {% block content %}{% endblock %} </div> </body> </html>

新增投票主題列表頁面範本 poll/default/templates/default/poll_list.html

{% extends "base.html" %} {% block content %} <h1>投票主題</h1> <ul> {% for poll in poll_list %} <li>{{ poll.date_created }} <a href="{{ poll.id }}/">{{ poll.subject }}</a></li> {% endfor %} </ul> {% endblock %}

:bulb: 通用視圖在未特別指定頁面範本的情況下,會自動將所處的應用程式名稱加在頁面範本檔案之前。以本例來說,在 default 應用程式下繼承 ListViewPollList,預設會到範本搜尋路徑取用 default/poll_list.html 當做頁面範本。

:bulb: 在專案設定值未指定範本搜尋路徑,而 APP_DIRS 被啟用的狀況下,會自動將 default 應用程式資料夾下的 templates 加入搜尋路徑,因此 poll_list.html 要被放在 poll/default/templates/default/ 底下。

啟動網站,在網址列輸入 http://your-host-address/poll/ 會出現以下頁面。
(註:your-host-address 請自行置換為執行專案的主機位址)

投票主題檢視

網址

修改檔案 poll/default/urls.py

urlpatterns = [ path('poll/', views.PollList.as_view()), path('poll/<int:pk>/', views.PollDetail.as_view()), ]

視圖

修改 poll/default/views.py:

from django.shortcuts import render from django.views.generic import ListView, DetailView from .models import *
# 投票主題檢視 class PollDetail(DetailView): model = Poll # 取得額外資料供頁面範本顯示 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) options = Option.objects.filter(poll_id=self.kwargs['pk']) context['options'] = options return context

範本

新增投票主題檢視頁面範本檔案 poll/default/templates/default/poll_detail.html

{% extends "base.html" %} {% block content %} <h1>{{ poll.subject }}</h1> <ul> {% for option in options %} <li>{{ option.title }}</li> {% endfor %} </ul> {% endblock %}

啟動網站,在網址列輸入 http://your-host-address/poll/1/ 會出現以下頁
(註:your-host-address 請自行置換為執行專案的主機位址)

投票

這個範例的投票動作很簡單,不記錄投票的其他相關資訊,例:投票者、投票時間…等,僅單純增加票數而已。因此之前在定義資料模型的時候僅透過 Option 中的 count 欄位來記錄選項被投了幾次。

投票的流程簡化如下:在檢視投票主題時,可以直接點選該主題下的投票選項進行投票,投票後自動返回所屬投票主題檢視頁面。

網址

修改 poll/default/urls.py

path('poll/<int:pk>/', views.PollDetail.as_view()), path('option/<int:pk>/', views.PollVote.as_view()), ]

視圖

修改 poll/default/views.py

from django.shortcuts import render from django.views.generic import ListView, DetailView, RedirectView from .models import *
# 投票 class PollVote(RedirectView): def get_redirect_url(self, *args, **kwargs): option = Option.objects.get(id=self.kwargs['pk']) option.count += 1 # 將選項的票數+1 option.save() # 儲存至資料庫 return "/poll/"+str(option.poll_id)+"/"

:bulb: 如果要轉址的目的頁面是固定不變的,可以直接指定 RedirectViewredirect_url 就好了,例:

class StaticRedirectView(RedirectView):
    redirect_url = "/"

範本

在增加了票數之後,就直接轉址回所屬的投票主題檢視頁面,所以這個功能不需要定義頁面範本。