回上方

實戰:留言板

建立專案與應用程式

我們要建立一個留言板的應用程式

(1)在終端機中下達指令建立一個新的專案

django-admin.py startproject guestbook

打完指令後,會產生一個guestbook的資料夾

guestbook/
    manage.py
    guestbook/
        __init__.py
        settings.py
        urls.py
        wsgi.py

(2)建立一個應用程式

cd guestbook python manage.py startapp web

修改 guestbook/guestbook/settings.py

ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'web', ]
  • 修改第 28 行:允許以任何主機名稱來存取專案網站。
  • 新增第 40 行:將方才新增的應用程式 web 加入專案中。
LANGUAGE_CODE = 'zh-hant' TIME_ZONE = 'Asia/Taipei'
  • 修改第 107 行,將預設的管理介面語系改為正體中文。
  • 修改第 109 行,將時區改為臺北時間。

定義資料模型

修改 guestbook/web/models.py

from django.db import models # Create your models here. class Message(models.Model): user = models.CharField("姓名", max_length=50) subject = models.CharField("主旨", max_length=200) content = models.TextField("內容") publication_date = models.DateTimeField("留言日期", auto_now_add=True) def __str__(self): return self.subject
  • 新增第 5 - 12 行,定義留言資料模型
    • 第 11, 12 行,定義 __str__() 方法,回傳資料代表字串

執行以下指令建立資料庫

python manage.py makemigrations python manage.py migrate python manage.py createsuperuser
  • 第 1 行,建立資料庫異動腳本
  • 第 2 行,將異動腳本實際套用到資料庫
  • 第 3 行,建立網站管理帳號

完成後,啟用專案網站服務

python manage.py runserver 0:80

視圖、網址、範本、表單

我們要建立相對應的網頁,首先定義專案的路徑規則。開啟 guestbook/guestbook/urls.py,修改為以下程式碼:

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

接著定義自訂應用程式 web 的路徑規則。新增檔案 guestbook/web/urls.py

from django.urls import path from django.views.generic import RedirectView from .views import * urlpatterns = [ path('', RedirectView.as_view(url='message/')), path('message/', MessageList.as_view()), path('message/<int:pk>/', MessageDetail.as_view()), path('message/create/', MessageCreate.as_view()), ]

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

from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView from django.urls import reverse from .models import Message # 留言列表 class MessageList(ListView): model = Message ordering = ['-id'] # 以 id 欄位值由大至小反向排序 # 留言檢視 class MessageDetail(DetailView): model = Message # 新增留言 class MessageCreate(CreateView): model = Message fields = ['user', 'subject', 'content'] # 僅顯示 user, subject, content 這 3 個欄位 success_url = '/message/' # 新增成功後,導向留言列表 template_name = 'form.html' # 指定欲使用的頁面範本

建立目錄 guestbook/web/templates/web

新增專案網站基底範本 guestbook/web/templates/base.html

<!DOCTYPE html> <html lang="zh-hant"> <head> <title>留言板</title> </head> <body> <h1>留言板</h1> <div> <a href="/">首頁</a> <a href="/message/create/">新增留言</a> </div> <div> {% block content %}{% endblock %} </div> </body> </html>

新增留言列表頁面範本 guestbook/web/templates/web/message_list.html

{% extends 'base.html' %} {% block content %} <ul> {% for message in message_list %} <li> {{ message.publication_date }} <a href="{{ message.id }}">{{ message.subject }}</a> </li> {% endfor %} </ul> {% endblock %}

新增留言檢視頁面範本 guestbook/web/templates/web/message_detail.html

{% extends "base.html" %} {% block content %} <h2>姓名</h2> {{ message.user }}<BR> <h2>主旨</h2> {{ message.subject }}<BR> <h2>內容</h2> {{ message.content|linebreaks }}<BR> {% endblock %}

新增共用表單頁面範本 guestbook/web/templates/form.html

{% extends 'base.html' %} {% block content %} <form action="" method="post"> {% csrf_token %} <table> {{ form.as_table }} </table> <input type="submit" value="送出" /> </form> {% endblock %}

使用者登入與登出

修改專案設定檔 guestbook/guestbook/settings.py,新增以下 2 行

# 登入後重新導向首頁 (預設會導向 /accounts/profile/) LOGIN_REDIRECT_URL = '/'

修改 guestbook/guestbook/urls.py

urlpatterns = [ path('admin/', admin.site.urls), path('', include('web.urls')), path('accounts/', include('django.contrib.auth.urls')), ]

開啟 guestbook/guestbook/settings.py,修改程式碼: 第4行

TEMPLATES = [ { ... 'DIRS': ['templates'], 'APP_DIRS': True, ...

新增資料夾 guestbook/templates/registration

新增登入頁面範本 guestbook/templates/registration/login.html

{% extends "base.html" %} {% block content %} <form action="" method="post"> {% csrf_token %} {{ form.as_p }} <div> <input type="submit" value="登入"> </div> </form> {% endblock %}

新增登出頁面範本 guestbook/templates/registration/logged_out.html

{% extends "bast.html" %} {% block content %} <p>您已登出!!</p> <a href="{% url 'login'%}">請按此處重新登入</a> {% endblock %}

修改專案基底頁面範本 guestbook/web/templates/base.htm,修改為以下程式碼:

<!DOCTYPE html> <html lang="zh-hant"> <head> <title>留言板</title> </head> <body> <h1>留言板</h1> <div> <a href="/">首頁</a> <a href="/message/create">新增留言</a> {% if user.is_authenticated %} {{ user.username }} <a href="{% url 'logout' %}">登出</a> {% else %} <a href="{% url 'login' %}">登入</a> {% endif %} </div> <hr> <div> {% block content %}{% endblock %} </div> </body> </html>

限制登入後才能刪除留言

開啟 guestbook/web/urls.py,修改為以下程式碼:

from django.urls import path from django.views.generic import RedirectView from .views import * urlpatterns = [ path('', RedirectView.as_view(url='message/')), path('message/', MessageList.as_view()), path('message/<int:pk>/', MessageDetail.as_view()), path('message/create/', MessageCreate.as_view()), path('message/<int:pk>/delete/', MessageDelete.as_view()), ]
  • 新增第 10 行,定義「刪除留言」的存取路徑

開啟 guestbook/web/views.py,新增以下程式碼:

# 刪除留言 class MessageDelete(DeleteView): model = Message success_url = '/message/' # 刪除成功返回留言列表 template_name = 'confirm_delete.html'

新增刪除留言頁面範本 guestbook/web/templates/confirm_delete.html

{% extends "base.html" %} {% block content %} <h2>刪除記錄</h2> <p>您確定要刪除「{{ object }}」這筆記錄嗎?</p> <form action="" method="POST"> {% csrf_token %} <input type="submit" action="" value="是的,我要刪除" /> </form> {% endblock %}

開啟 guestbook/web/templates/web/message_list.html,修改為以下程式碼:

{% extends "base.html" %} {% block content %} <ul> {% for message in message_list %} <li> {{ message.publication_date }} {% if user.is_authenticated %} <a href="{{ message.id }}/delete/">刪除</a> {% endif %} <a href="{{ message.id }}/">{{ message.subject }}</a> </li> {% endfor %} </ul> {% endblock %}