視圖、網址、範本
使用者透過瀏覽器存取 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
範本
頁面範本要放在哪裡?
在專案的 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 %}
通用視圖在未特別指定頁面範本的情況下,會自動將所處的應用程式名稱加在頁面範本檔案之前。以本例來說,在 default
應用程式下繼承 ListView
的 PollList
,預設會到範本搜尋路徑取用 default/poll_list.html
當做頁面範本。
在專案設定值未指定範本搜尋路徑,而 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)+"/"
如果要轉址的目的頁面是固定不變的,可以直接指定 RedirectView
的 redirect_url
就好了,例:
class StaticRedirectView(RedirectView):
redirect_url = "/"
範本
在增加了票數之後,就直接轉址回所屬的投票主題檢視頁面,所以這個功能不需要定義頁面範本。