Django -- 從平凡到超凡

第 8 章    在頁面顯示資料

(1) 在部落格頁面顯示文章

∗ 顯示部落格文章

▸ 目前進入部落格頁面僅顯示「部落格說 -- Hello world!」等字樣,現在改為顯示部落格文章,修改 views 程式:

article/views.py
from django.shortcuts import render

from article.models import Article


def article(request):
    '''
    Render the article page
    '''
    articles = Article.objects.all()
    context = {'articles':articles}
    return render(request, 'article/article.html', context)
✶ 匯入 ArticleComment model
articles = ...:利用 ORM之 查詢 (Query) 指令取出所有資料
context = ...:利用範本變數 articles 將查詢結果傳至範本

▸ 修改範本:

article.html
  ...
  <body>
    {% include 'main/menu.html' %}
    <h2>部落格說--Hello world!</h2>
    <h2>歡迎來到我的部落格</h2>
    <br> 
    {% for article in articles %}
      <h3>{{ article.title }}</h3>
      <p>發表時間:{{ article.pubDateTime|date:'Y-m-d H:i' }}</p>
      <div class="articleContent">{{ article.content }}</div>
      <hr>
    {% endfor %}
  </body>
</html>
{% for article in articles %}:views 程式傳入 articles 串列,此迴圈針對每一筆資料進行處理,每次迴圈所使用的物件稱為 article
{{ article.title }}:顯示 articletitle 欄位內容
{{ article.pubDateTime|date:'Y-m-d H:i' }}: 顯示 pubDateTime 欄位內容
# | 符號稱為過濾器 (Filter),針對資料做進一步處理
# date: 設定資料之日期顯示格式
# Y-m-d:年月日 (4 碼西元年),以短橫線連結,後接一個空白
# H:i:時分(24 時制),中間加冒號
{{ article.content }}:顯示文章內容,並加上一個 articleContent 類別,方便之後的 CSS 樣式設定
✶ 測試:發現文章內容並未斷行 (HTML中,\n 並無效應)
article non-break
# 加上 linebreaks
<div class="articleContent">{{ article.content|linebreaks }}<div>
article break
✶ 再次測試並檢視原始碼:範本引擎將 \n 置換為 <br />, 並且將文章內容以 <p> 段落標籤包住,如下:
     <h3>如何像電腦科學家一樣思考</h3>
      <p>發表時間:...</p>
      <div class="articleContent">
      <p>如何像電腦科學家一樣思考<br />
         如何像電腦科學家一樣思考<br />
         如何像電腦科學家一樣思考<br />
         ...
      <p>
      <p>讚:7</p>
      <hr>

▸ 加上 CSS 設定,讓文章呈現邊框及背景:新增 article/static/article/css/article.css 檔案 (當然要先建立以下目錄: article/static, article/static/article, article/static/article/css)

.articleContent {
  padding: 20px;
  background-color: #e9e9e9;
  border: thin solid gray;
  border-radius: 10px;
}

▸ 在 article.html 加上 CSS 連結:

...
<link rel="stylesheet" href="{% static 'main/css/main.css' %}">
<link rel="stylesheet" href="{% static 'article/css/article.css' %}">
</head>

▸ 測試 (可能需要重新啟動伺服器)

article CSS

∗ 僅顯示文章部份內容

▸ 由於文章內容可能很長,應先顯示部份內容,訪客有興趣的話再看全部內容:利用範本過濾器 truncate_html 截斷文章,只顯示部份內容

{{ article.content|linebreaks|truncatechars_html:30 }}
✶ 僅顯示 30 個字元 (包含 3 個句點),其餘截斷,而且保持 HTML 標籤正確配對
--> 測試:文章內容截斷,並以 3 個句點結束
article Truncate

▸ 註:另有

truncatechars 過濾器:不管 HTML 標籤配對
truncatewords_html 過濾器:不截斷英文單字

(2) 在每篇文章下方顯示所屬留言

∗ 在顯示文章時,一併顯示其所屬留言

▸ 在 views 程式中,同時取出文章與留言

article/views.py
...
from article.models import Article, Comment


def article(request):
    '''
    Render the article page
    '''
    articles = Article.objects.all()
    articles = {}
    for article in Article.objects.all():
        articles.update({article:Comment.objects.filter(article=article)})
    context = {'articles':articles}
    return render(request, 'article/article.html', context)
✶ 增加匯入 Comment 類別
✶ 將 articles 變數改為一個字典 (Dictionary),其中每個項目的鍵 (Key) 就是文章物件,而其對應值 (Value) 就是所屬留言的串列:
articles = {
  article1: [comment1-1, comment1-2, comment1-3, ...],
  article2: [comment2-1, comment2-2, comment2-3, ...],
  ...
}
✶ 在每一篇文章迴圈中利用字典方法 update() 來將該項目附加到 articles 字典中
✶ 最後 2 行:將 articles 字典傳送到範本中 (範本變數名稱亦為 articles)
✶ 註:Python 3.6 開始,字典項目依照輸入的順序排序,因此文章還是會依照日期順序來顯示

∗ 頁面顯示文章及留言

article.html:

    ...
    <h1>歡迎來到我的部落格</h1>
    <br>
    {% for article in articles %}
      ...
    {% endfor %}
{% for article, comments in articles.items %} <h3>{{ article.title }}</h3> <p>發表時間:{{ article.pubDateTime|date:'Y-m-d H:i' }}</p> <div class="articleContent">{{ article.content|linebreaks|truncatechars_html:30 }}</div> {% for comment in comments %} <div class="commentDiv"> <span class="comment">{{ comment.content }}</span> <br> <span class="commentTime">{{ comment.pubDateTime|date:'m月d日 H:i' }}</span> </div> {% endfor %} {% endfor %}
...

▸ 利用 2 層巢狀迴圈顯示文章及留言,外層迴圈的每一個項目是文章,內層迴圈的每一個項目文章的所屬留言

▸ 以迴圈處理字典的範本指令格式如下:

{% for key, value in <dict>.items %}
  {{ key }}: {{ value }}
{% endfor %}
因此,取用文章及留言的迴圈語法為 {% for article, comments in articles.items %}

▸ 每個留言設定 commentDiv, comment, commentTime 等 CSS 類別, 留言字體設定較小,日期設為灰色:

article.css
.articleContent {
  ...
}

.commentDiv {
  margin-top: 1em;
}

.comment {
  font-size: 0.8em;
}

.commentTime {
  font-size: 0.6em;
  color: #777777;
}
--> 測試
article with comment

(3) 小結

∗ 上推專案到 Github

▸ Right click project --> Team --> Commit --> Commit message: Chapter 8 finished --> Commit and Push

∗ 練習

▸ 在 bookstore 專案的 book app 中撰寫相關程式, 讓所有書籍資料在頁面顯示

上一章       下一章