案例:數位助理
前言
第 8 課與第 9 課已經分別實作了數位助理專案的日誌以及記帳的功能,接著來進行版面美化的工作。在這個案例中,同樣直接透過 CDN 來引用 Bootstrap 框架以及 Font Awesome 來美化網站頁面。
修改網站基底範本
建立導覽列
新增 assistant/templates/navbar.html
<nav class="navbar navbar-expand-sm navbar-dark bg-dark mb-2">
<div class="navbar-brand"><i class="far fa-address-card"></i> 數位助理</div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ml-auto">
{% if user.is_authenticated %}
<li class="nav-item"><a href="/" class="nav-link"><i class="fas fa-book"></i> 日記</a></li>
<li class="nav-item"><a href="/journal/create" class="nav-link"><i class="fas fa-edit"></i> 寫日誌</a></li>
<li class="nav-item"><a href="/expenses/" class="nav-link"><i class="fas fa-money-check"></i> 帳本</a></li>
<li class="nav-item"><a href="/expenses/create" class="nav-link"><i class="fas fa-money-check-alt"></i> 記帳</a></li>
<li class="nav-item"><a href="/accounts/logout" class="nav-link btn btn-sm btn-primary">{{ user.username }} <i class="fas fa-sign-out-alt"></i> 登出</a></li>
{% else %}
<li class="nav-item"><a href="{% url 'login' %}" class="nav-link btn btn-sm btn-primary"><i class="fas fa-sign-in-alt"></i> 登入</a></li>
{% endif %}
</ul>
</div>
</nav>
引用 Bootstrap、FontAwesome 以及導覽列
將網站基底頁面範本 assistant/templates/base.html
修改如下:
<!doctype html>
<html lang="zh-hant">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
<title>數位助理</title>
</head>
<body>
<div class="container">
{% include "navbar.html" %}
<div id="content">{% block content %}{% endblock %}</div>
</div>
</body>
</html>
修改後,導覽列的顯示效果如下:
美化日誌功能
使用者登入
先前在表單所使用的頁面範本中,要產生每個欄位的輸入元件時,都是使用 {{ form.as_p }}
或 {{ form.as_table }}
來將頁面範本接收到的 form
變數中關於欄位的定義自動展開。這種方式的好處是方便,但是較難針對欄位的外觀做較細部的處理。
另一種方式則是自行撰寫所需欄位的 HTML 碼,只要輸入元件的 name
屬性與其所屬的資料模型或表單定義內的欄位名稱相同,就可以用來在頁面上接收使用者的輸入,在送出表單後,Django 也能正常處理。以下示範不透過 form
變數來自動產生輸入元件的 HTML 碼,而改採使用者自行撰寫的方式來修改使用者登入表單的頁面範本。
修改 assistant/templates/registration/login.html
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p class="alert alert-danger">帳號或密碼不符合,請再試一次。</p>
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="h3 mb5">請輸入您的帳號密碼</div>
<div class="form-inline">
<input name="username" autofocus required id="id_username" maxlength="254" type="text" class="form-control mr-2" placeholder="帳號">
<input name="password" required id="id_password" type="password" class="form-control mr-2" placeholder="密碼">
<input type="submit" value="login" class="form-control btn-primary"/>
</div>
</form>
{% endblock %}
使用者登出
修改 assistant/templates/registration/logged_out.html
{% extends "base.html" %}
{% block content %}
<p class="alert alert-info">您已登出!!</p>
<a href="{% url 'login'%}" class="btn btn-primary">請按此處重新<i class="fas fa-sign-in-alt"></i> 登入</a>
{% endblock %}
Bootstrap 框架的 alert
類別是套用在包覆警告、通知訊息用的容器上,需額外搭配相對應的類別,以產生不同的前背景配色組合:
搭配類別 |
外觀示例 |
alert-primary |
|
alert-secondary |
|
alert-success |
|
alert-danger |
|
alert-warning |
|
alert-info |
|
alert-light |
|
alert-dark |
|
日誌列表
修改 assistant/templates/journal/journal_list.html
:
{% extends "base.html" %}
{% block content %}
<h2><i class="fas fa-book"></i> 我的日誌:</h2>
<table class="table table-sm">
<tr><td>時間</td><td>項目</td><td>功能</td></tr>
{% for journal in journal_list %}
<tr>
<td>({{ journal.created|date:"l" }}){{ journal.created }}</td>
<td><a href="{{ journal.id }}/update/">{{journal.content}}</a></td>
<td><a href="{{ journal.id }}/delete/" class="btn btn-sm btn-danger py-0 px-1"><i class="fas fa-trash-alt"></i> 刪除</a></td>
</tr>
{% endfor %}
</table>
{% include 'pagination.html' %}
{% endblock %}
修正時間格式
日誌列表的時間格式目前顯示的語言是英文,若要修正為中文的話,需要修改專案設定值。
修改 assistant/assistant/settings.py
,將 LANGUAGE_CODE
以及 TIME_ZONE
的值修正如下:
LANGUAGE_CODE = 'zh-hant'
TIME_ZONE = 'Asia/Taipei'
美化分頁連結
修改 assistant/templates/pagination.html
{% if is_paginated %}
<div>
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}" class="btn btn-sm btn-primary"><i class="fas fa-chevron-circle-left"></i>上一頁</a>
{% endif %}
{% for page in paginator.page_range %}
{% if page == page_obj.number %}
<button class="btn btn-sm btn-primary" disabled>{{ page }}</button>
{% else %}
<a href="?page={{ page }}" class="btn btn-sm btn-primary">{{ page }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}" class="btn btn-sm btn-primary">下一頁<i class="fas fa-chevron-circle-right"></i></a>
{% endif %}
</div>
{% endif %}
修改項目主要有 2 個:
- 為「上一頁」與「下一頁」加上適合的圖示
- 為所有的連結套用
btn btn-sm btn-primary
類別
我的帳本
修改 assistant/templates/expenses/expense_list.html
{% extends "base.html" %}
{% block content %}
<h2><i class="fas fa-money-check"></i> 我的帳本:</h2>
<table class="table table-sm">
<tr>
<th>時間</th>
<th>項目</th>
<th>類別</th>
<th>金額</th>
<th>功能</th>
</tr>
{% for expense in expense_list %}
<tr>
<td>({{ expense.time|date:"l" }}) {{ expense.time }}</td>
<td><a href="{{ expense.id }}/update/">{{ expense.item }}</a></td>
<td>{{ expense.get_category_display }}</td>
<td>{{ expense.amount }}</td>
<td><a href="{{ expense.id }}/delete/" class="btn btn-sm btn-danger py-0 px-1"><i class="fas fa-trash-alt"></i> 刪除</a></td>
</tr>
{% endfor %}
</table>
{% include 'pagination.html' %}
{% endblock content %}
寫日誌與記帳
修改頁面範本
修改 assistant/templates/form.html
{% extends "base.html" %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table class="table table-sm">
{{ form.as_table }}
</table>
<input type="submit" value="送出" class="btn btn-sm btn-primary"/>
</form>
{% endblock %}
美化表單
頁面範本 assistant/templates/form.html
中採用了 {{ form.as_table }}
的方式來產生輸入元件的 HTML 碼,所以才能讓新增、修改日誌以及記帳等功能共用同一個頁面範本。但是這樣一來,也無法直接在頁面範本中指定 <input>
標籤來套用 form-control
類別來修改它們的外觀。
如果想要在頁面範本中保持採用 {{ form.as_table }}
讓多項輸要輸入資料的功能可以共用同一個頁面範本的話,該如何針對自動產生的輸入元件的標籤做相關的調整呢?官方的標準做法是自行撰寫表單類別,在類別中指定每個輸入欄位的相關設定。示範如下:
新增 assistant/journal/forms.py
,在其中自行定義表單類別:
from django.forms import ModelForm, Textarea
from .models import Journal
class JournalForm(ModelForm):
class Meta:
model = Journal
fields = ['content']
widgets = {
'content': Textarea(attrs={'class': 'form-control'}),
}
自訂了表單定義後,接著修改通用視圖,指定使用自訂的表單定義。
請修改 assistant/journal/views.py
,指定 JournalCreate
、 JournalUpdate
等 2 個 class 的 form_class
屬性:
from .forms import JournalForm
class JournalCreate(LoginRequiredMixin, CreateView):
form_class = JournalForm
success_url = '/journal/'
template_name = 'form.html'
class JournalUpdate(LoginRequiredMixin, UpdateView):
model = Expense
form_class = JournalForm
success_url = '/journal/'
template_name = 'form.html'
修改處如下:
- 新增第 5 行,引用方才定義的自訂表單
JournalForm
- 新增第 16, 24 行,透過
form_class
屬性指定使用自訂表單定義 JournalForm
- 刪除
JournalCreate
以及 JournalUpdate
下的 fields
屬性設定
- 刪除
JournalCreate
類別下的 model
屬性設定
JournalUpdate
需要先載入欲修改的紀錄,再放到表單上,所以 JournalUpdate
裡的 model
屬性設定不可以移除
同理,要修改記帳功能表單的外觀,也要修改 expenses
應用程式的 forms.py
以及 views.py
。新增自訂表單定義 assistant/expenses/forms.py
:
from django.forms import ModelForm, TextInput, Select, NumberInput
from .models import Expense
class ExpenseForm(ModelForm):
class Meta:
model = Expense
fields = '__all__'
widgets = {
'item': TextInput(attrs={'class': 'form-control'}),
'category': Select(attrs={'class': 'form-control'}),
'amount': NumberInput(attrs={'class': 'form-control'}),
}
修改 assistant/expenses/view.py
,指定 ExpenseCreate
與 ExpenseUpdate
這兩個通用視圖使用方才自定義的 ExpenseForm
:
from .forms import ExpenseForm
class ExpenseCreate(LoginRequiredMixin, CreateView):
form_class = ExpenseForm
template_name = 'form.html'
def get_success_url(self):
return reverse('expense_list')
class ExpenseUpdate(LoginRequiredMixin, UpdateView):
model = Expense
form_class = ExpenseForm
template_name = 'form.html'
def get_success_url(self):
return reverse('expense_list')
修改方式請參考前一段關於 JournalCreate
與 JournalUpdate
的修改說明。
案例:數位助理
前言
第 8 課與第 9 課已經分別實作了數位助理專案的日誌以及記帳的功能,接著來進行版面美化的工作。在這個案例中,同樣直接透過 CDN 來引用 Bootstrap 框架以及 Font Awesome 來美化網站頁面。
修改網站基底範本
建立導覽列
新增
assistant/templates/navbar.html
引用 Bootstrap、FontAwesome 以及導覽列
將網站基底頁面範本
assistant/templates/base.html
修改如下:修改後,導覽列的顯示效果如下:
美化日誌功能
使用者登入
先前在表單所使用的頁面範本中,要產生每個欄位的輸入元件時,都是使用
{{ form.as_p }}
或{{ form.as_table }}
來將頁面範本接收到的form
變數中關於欄位的定義自動展開。這種方式的好處是方便,但是較難針對欄位的外觀做較細部的處理。另一種方式則是自行撰寫所需欄位的 HTML 碼,只要輸入元件的
name
屬性與其所屬的資料模型或表單定義內的欄位名稱相同,就可以用來在頁面上接收使用者的輸入,在送出表單後,Django 也能正常處理。以下示範不透過form
變數來自動產生輸入元件的 HTML 碼,而改採使用者自行撰寫的方式來修改使用者登入表單的頁面範本。修改
assistant/templates/registration/login.html
使用者登出
修改
assistant/templates/registration/logged_out.html
Bootstrap 框架的
alert
類別是套用在包覆警告、通知訊息用的容器上,需額外搭配相對應的類別,以產生不同的前背景配色組合:alert-primary
alert-secondary
alert-success
alert-danger
alert-warning
alert-info
alert-light
alert-dark
日誌列表
修改
assistant/templates/journal/journal_list.html
:修正時間格式
日誌列表的時間格式目前顯示的語言是英文,若要修正為中文的話,需要修改專案設定值。
修改
assistant/assistant/settings.py
,將LANGUAGE_CODE
以及TIME_ZONE
的值修正如下:美化分頁連結
修改
assistant/templates/pagination.html
修改項目主要有 2 個:
btn btn-sm btn-primary
類別我的帳本
修改
assistant/templates/expenses/expense_list.html
寫日誌與記帳
修改頁面範本
修改
assistant/templates/form.html
美化表單
頁面範本
assistant/templates/form.html
中採用了{{ form.as_table }}
的方式來產生輸入元件的 HTML 碼,所以才能讓新增、修改日誌以及記帳等功能共用同一個頁面範本。但是這樣一來,也無法直接在頁面範本中指定<input>
標籤來套用form-control
類別來修改它們的外觀。如果想要在頁面範本中保持採用
{{ form.as_table }}
讓多項輸要輸入資料的功能可以共用同一個頁面範本的話,該如何針對自動產生的輸入元件的標籤做相關的調整呢?官方的標準做法是自行撰寫表單類別,在類別中指定每個輸入欄位的相關設定。示範如下:新增
assistant/journal/forms.py
,在其中自行定義表單類別:自訂了表單定義後,接著修改通用視圖,指定使用自訂的表單定義。
請修改
assistant/journal/views.py
,指定JournalCreate
、JournalUpdate
等 2 個 class 的form_class
屬性:修改處如下:
JournalForm
form_class
屬性指定使用自訂表單定義JournalForm
JournalCreate
以及JournalUpdate
下的fields
屬性設定JournalCreate
類別下的model
屬性設定JournalUpdate
需要先載入欲修改的紀錄,再放到表單上,所以JournalUpdate
裡的model
屬性設定不可以移除同理,要修改記帳功能表單的外觀,也要修改
expenses
應用程式的forms.py
以及views.py
。新增自訂表單定義assistant/expenses/forms.py
:修改
assistant/expenses/view.py
,指定ExpenseCreate
與ExpenseUpdate
這兩個通用視圖使用方才自定義的ExpenseForm
:修改方式請參考前一段關於
JournalCreate
與JournalUpdate
的修改說明。