iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
Python

Python 錦囊密技系列 第 27

【Python錦囊㊙️技27】輕鬆建構內容管理系統(CMS)

  • 分享至 

  • xImage
  •  

從本篇開始,我們以之前具備的Python技能建構各種應用系統,包括內容管理系統(Content Management System, CMS)、儀表板(Dashboard)...等,本文先研究【內容管理系統】(CMS)。

內容管理系統(Content Management System, CMS)

內容管理系統(CMS)可以是一個部落格(Blog)、新聞網站(News)、商品推薦文或人物誌(Biography),是每個企業都需要的應用系統,因應以上各種用途或使用者觀點,會有各種版面(Layout)的需求,因此,典型的CMS套件都會提供自訂模板(Templates)功能,而Jinja套件正好是製作模板最佳的工具,Django、Flask都支援Jinja,本系列以多次介紹Django,所以,就來比較【Django CMS】相關套件,如下圖:
https://ithelp.ithome.com.tw/upload/images/20241010/20001976vlkINGbXSg.png
圖一. 【Django CMS】比較表

  1. 前兩名為【Wagtail】、【Django CMS】,前者較為美觀,但較複雜,後者功能較陽春、較單純。
  2. 觀察比較表,種類(Category)分為3種,框架(Framework)、應用程式(App)及專案(Project),前者提供架構,可基於框架建置新專案,後兩者單純是一個專案,通常為追求彈性,會優先選擇前者。
  3. 經筆者測試後,【Wagtail】比【Django CMS】功能性較完整,且較具彈性。因此,決定採用【Wagtail】實作。

Wagtail 安裝

依照官方文件說明,步驟如下:

  1. 安裝Wagtail套件:
pip install wagtail
  1. 建置新專案(mysite):
wagtail start mysite
  1. 安裝專案所需套件:注意它會指定Django版本,可能會降級。
cd mysite
pip install -r requirements.txt
  1. 建置資料庫:
python manage.py migrate
  1. 建立系統管理員:
python manage.py createsuperuser
  1. 啟動專案:
python manage.py runserver
  1. 開啟瀏覽器,輸入URL:
http://localhost:8000/
  1. 輸入步驟5設定的系統管理員帳密,執行結果:
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976rXLeV5pVyP.png

實作

依照上節建立的專案,進行頁面模板設計。

  1. 進入系統管理頁面:
http://localhost:8000/admin
  1. 設定首頁:點選下圖紅框按鈕。
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976uel6jSxXCG.png

  2. 只能輸入標題(Title):
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976dnr3NCjJrz.png

  3. 確認輸入沒問題即可發行(Publish)到網站上:
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976a1hMsNLF0D.png

  4. 開啟瀏覽器測試,輸入URL:

http://localhost:8000/

修改首頁模板

  1. 先建立Model:修改F:\0_python\00_MY\0_ITHome\src\27\mysite\home\models.py,內容如下,加入內文(body),為可格式化的文字框(Rich Text Field)。
from django.db import models
from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

class HomePage(Page):
    # 定義 Rich Text Field, not mandatory
    body = RichTextField(blank=True)
    
    # 加入 body
    content_panels = Page.content_panels + [
        FieldPanel('body'),
    ]
  1. 更新資料庫:
python manage.py makemigrations
python manage.py migrate
  1. 修改新模型對應的模板(mysite\home\templates\home\home_page.html):加上page.body,對應models.py的body。
{% extends "base.html" %}
{% load static %}
{% load wagtailcore_tags %}

{% block body_class %}template-homepage{% endblock %}

{% block content %}
    {{ page.body|richtext }}
{% endblock content %}
  1. 再重新設定首頁除了標題(Title),還可以輸入內文(body):
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976Id4xTmPl6i.png

  2. 內文的編輯器可設定字體大小,並加入超連結、影像...等。
    https://ithelp.ithome.com.tw/upload/images/20241011/200019765aLIoxdRuI.png

  3. 切換至上方的【Promote】頁籤,可輸入slug、tag及頁面資訊,作為搜尋引擎的SEO,其中slug為URL以【/】隔開的最後一段字串。
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976aywmzoHfyZ.png

  4. 確認輸入沒問題即可發行(Publish)到網站上:
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976a1hMsNLF0D.png

  5. 開啟瀏覽器測試,輸入URL:

http://localhost:8000/
  1. 執行結果:
    https://ithelp.ithome.com.tw/upload/images/20241011/200019766f5OP0IYf0.png

作到這裡,我們就可完成一個單頁的網站,展示外部的新聞列表。

建置部落格(Blog)

接下來,我們建置一個多頁的網站,Wagtail是以子頁(Child page)排列在主頁內。

  1. 建立新的App(blog)。
python manage.py startapp blog
  1. 將新的App(blog)加入網站設定檔,Wagtail設定檔是mysite\mysite\settings\base.py,不是settings.py:
INSTALLED_APPS = [
    "home",
    "blog",
  1. 建立主頁的Model(mysite\blog/models.py):同上,加入intro的可格式化文字框(Rich Text Field)。
from django.db import models
from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

class BlogIndexPage(Page):
    intro = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('intro')
    ]
  1. 修改新模型對應的模板(mysite\blog\templates\blog\blog_index_page.html):加上page.intro,對應models.py的intro,下方還有page.get_children,會顯示所有子頁(Child page)。
{% extends "base.html" %}
{% load wagtailcore_tags %}
{% block body_class %}template-blogindexpage{% endblock %}
{% block content %}
    <h1>{{ page.title }}</h1>

    <div class="intro">{{ page.intro|richtext }}</div>

    {% for post in page.get_children %}
        <h2><a href="{% pageurl post %}">{{ post.title }}</a></h2>
        {{ post.specific.intro }}
        {{ post.specific.body|richtext }}
    {% endfor %}

{% endblock %}
  1. 修改Model(mysite\blog\models.py):加入BlogPage,定義子頁的欄位。
from wagtail.search import index
...
class BlogPage(Page):
    date = models.DateField("Post date")
    intro = models.CharField(max_length=250)
    body = RichTextField(blank=True)

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        FieldPanel('intro'),
        FieldPanel('body'),
    ]
  1. 修改子頁模型對應的模板(mysite\blog\templates\blog\blog_page.html):加上page.date、page.intro、page.body,對應models.py,使用page.get_parent.url回上頁。
{% extends "base.html" %}
{% load wagtailcore_tags %}
{% block body_class %}template-blogpage{% endblock %}

{% block content %}
    <h1>{{ page.title }}</h1>
    <p class="meta">{{ page.date }}</p>

    <div class="intro">{{ page.intro }}</div>

    {{ page.body|richtext }}

    <p><a href="{{ page.get_parent.url }}">Return to blog</a></p>

{% endblock %}
  1. 更新資料庫:
python manage.py makemigrations
python manage.py migrate
  1. 回系統管理首頁,再點選【Our Blog】。
http://localhost:8000/admin

https://ithelp.ithome.com.tw/upload/images/20241011/200019765UI5fIye1j.png

  1. 加入主頁:
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976aFdHgvZ3Om.png

  2. 加入子頁:
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976Hc3rDyz0E5.png

  3. 指定子頁模板:Blog page。
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976oPg66abbIn.png

  4. 開啟瀏覽器測試,輸入URL:

http://localhost:8000/blog
  1. 執行結果:主頁下會一併顯示所有子頁。
    https://ithelp.ithome.com.tw/upload/images/20241011/20001976lN2dEmDoip.png

作到這裡,完成一個部落格(Blog)建置。

結語

以上只是Wagtail入門的教學,更多的功能可參閱官方文件說明,不過對於筆者而言,最大的收穫是利用Model/Template對應一種網頁佈局(Layout),可以讓開發者自訂佈局,如果要進一步讓使用者自訂佈局,可以將Model變成兩個資料表,一個是主表定義Template檔名,另一個子表對應Template內的欄位,就不需要每次增加一種佈局,就必須更新資料庫。

本系列的程式碼會統一放在GitHub,本篇的程式放在src/27資料夾,歡迎讀者下載測試,如有錯誤或疏漏,請不吝指正。


上一篇
【Python錦囊㊙️技26】微服務 (Microservices) 【3】-- 服務導向架構(SOA)
下一篇
【Python錦囊㊙️技28】輕鬆建構儀表板(Dashboard)
系列文
Python 錦囊密技30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言