在前一篇測試中已下載 EasyUI for jQuery 並建立好 easyuicms 專案的基本目錄結構, 接下來要將解壓縮好的 EasyUI 程式與樣式檔放進專案的 static 目錄下, 建立網頁模板檔案後放到 templates 目錄下, 然後建立一個 App 來回應客戶端請求.
本系列之前的測試文章參考 :
4. 配置靜態檔案 :
首先將解壓縮 EasyUI for jQuery 後會得到 EasyUI 主程式 jquery.easyui.min.js, 以及其所依賴的 jquery.min.js, 需將這兩個程式檔複製到 static/js 目錄下. 接著在 js 下新建一個 locale 子目錄, 把解壓縮目錄 locale 下的繁體中文語言檔 easyui-lang-zh_TW.js 放在 locale 下. EasyUI 的核心程式碼和預設資源檔案 (例如 jquery.easyui.min.js) 內建的文字提示與日期格式等都是英文, 這個語言檔可以讓系統顯示中的文字改為繁體中文.
EasyUI 提供許多主題布景樣式, 全部放在解壓縮目錄 themes 下, 初期為了簡單考量, 僅使用 default 預設主題, 所以在 themes 目錄下新建一個 default 子目錄, 然後將解壓縮目錄 themes/default 下的 easyui.css 複製到 /static/themes/default 下. 另外, 解壓縮目錄 themes 下的 icon.css 也要複製到 static/themes 下, 這是 EasyUI 元件使用的圖示 (例如按鈕上的小圖標, 樹狀結構的箭頭等) 之樣式, 此為所有主題共用, 不隨主題改變.
用 tree 指令檢視目前目錄結構 :
D:\django>tree easyuicms /f
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\DJANGO\EASYUICMS
│ db.sqlite3
│ manage.py
│
├─easyuicms
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-310.pyc
│ urls.cpython-310.pyc
│ wsgi.cpython-310.pyc
│ __init__.cpython-310.pyc
│
├─static
│ ├─images
│ ├─js
│ │ │ jquery.easyui.min.js
│ │ │ jquery.min.js
│ │ │
│ │ └─locale
│ │ easyui-lang-zh_TW.js
│ │
│ └─themes
│ │ icon.css
│ │
│ └─default
│ easyui.css
│
└─templates
此架構保留了未來需要套用其它主題樣式時之彈性, 其它主題可在 static/themes 下建立目錄並複製其 easyui.css 在該主題之目錄下. 另外若要支援多語系, 將語系檔複製到 locale 下即可.
5. 編輯網頁模板 :
網頁模板用來讓 Django 動態渲染網頁輸出, Django 的模板系統採用 Jinja2, 可以一層一層用 extends 繼承, 用法參考 :
首先編輯基礎模板 base.htm :
<!-- base.htm -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{% block title %}{% endblock %}</title>
{% block link %}{% endblock %}
{% block script %}{% endblock %}
<style>
{% block style %}{% endblock %}
</style>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
基礎模板中定義了 title, link, script, style, 以及 body 五個區塊 (block) 讓子模板繼承時去填充. 接下來編輯繼承 base.htm 的子模板 easyui.htm :
<!-- easyui.htm -->
{% extends "base.htm" %}
{% load static %}
{% block link %}
<link id="theme" rel="stylesheet" href='{% static "themes/default/easyui.css" %}'>
<link rel="stylesheet" href='{% static "themes/icon.css" %}'>
{% endblock %}
{% block script %}
<script src='{% static "js/jquery.min.js" %}'></script>
<script src='{% static "js/jquery.easyui.min.js" %}'></script>
<script src='{% static "js/locale/easyui-lang-zh_TW.js" %}'></script>
{% endblock %}
子模板必須在開頭使用 extends 指令繼承父模板. 此 easyui.htm 模板因為要引入靜態檔案, 所以需在引入前用模板標籤 {% load static %} 告訴 Django 的模板引擎載入靜態檔案相關的模板標籤 {% static}, 這樣才能使用 {% static %} 標籤來生成靜態檔案的正確路徑.
這樣就可以繼承 easyui.htm 來撰寫 App 要渲染的網頁模板了, 結構如下 :
<!-- demo.htm -->
{% extends "easyui.htm" %}
{% block body %}
<!-- 網頁內容寫在下面 -->
<b>Hello World!</b>
{% endblock %}
將此三個模板檔放到 templates 下備用.
用 tree 指令檢視目前目錄結構 :
D:\django>tree easyuicms /f
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\DJANGO\EASYUICMS
│ db.sqlite3
│ manage.py
│
├─easyuicms
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-310.pyc
│ urls.cpython-310.pyc
│ wsgi.cpython-310.pyc
│ __init__.cpython-310.pyc
│
├─static
│ ├─images
│ ├─js
│ │ │ jquery.easyui.min.js
│ │ │ jquery.min.js
│ │ │
│ │ └─locale
│ │ easyui-lang-zh_TW.js
│ │
│ └─themes
│ │ icon.css
│ │
│ └─default
│ easyui.css
│
└─templates
base.htm
demo.htm
easyui.htm
6. 建立應用程式 (App) :
App 是 Django 專案中具有獨立功能的可插拔元件, 亦即可將網頁專案的服務邏輯按照功能切割為數個 App 以符合軟體工程中元件可重用 (reusable) 之要求, 每一個 App 可以在最小程度的調整後移植到其他專案中使用.
此處要建立一個 app 來展示 EasyUI 的常用元件功能, 建立 App 的指令格式如下 :
python manage.py startapp <AppName>
在上層專案目錄下, 用下列指令建立一個名為 demo 的 app :
D:\django\easyuicms>python manage.py startapp demo
跳到上一層用 tree 檢視目錄結構 :
D:\django\easyuicms>cd ..
D:\django>tree easyuicms /f
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\DJANGO\EASYUICMS
│ db.sqlite3
│ manage.py
│
├─demo
│ │ admin.py
│ │ apps.py
│ │ models.py
│ │ tests.py
│ │ views.py
│ │ __init__.py
│ │
│ └─migrations
│ __init__.py
│
├─easyuicms
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-310.pyc
│ urls.cpython-310.pyc
│ wsgi.cpython-310.pyc
│ __init__.cpython-310.pyc
│
├─static
│ ├─images
│ ├─js
│ │ │ jquery.easyui.min.js
│ │ │ jquery.min.js
│ │ │
│ │ └─locale
│ │ easyui-lang-zh_TW.js
│ │
│ └─themes
│ │ icon.css
│ │
│ └─default
│ easyui.css
│
└─templates
base.htm
demo.htm
easyui.htm
可見在上層專案目錄下多了一個 demo 子目錄, 其下之檔案用途說明如下表 :
| App 檔案目錄 | 說明 |
| migrations | 紀錄與資料庫版本與資料模型變更相關之檔案 (用來同步模型與資料庫) |
| __init__.py | 空檔案, 使 App 目錄形式上符合 Python 套件要求 |
| admin.py | 用來註冊資料模型以便能於管理網頁中管理資料表 |
| apps.py | 儲存與此 App 相關之設定 |
| models.py | 儲存 App 資料模型定義以及資料間之關係 |
| test.py | 儲存測試程式碼 |
| views.py | 為 urls.py 處理 HTTP 要求與回應之程式檔 |
其中只有 admin.py, models.py, 以及 views.py 這三個檔案需要修改, 其餘都不用改.
7. 修改專案設定檔 settings.py :
完成上面靜態檔案與網頁模板配置, 以及 App 的新增後, 必須修改下層專案目錄下的 settings.py 才會生效, 用文字編輯器開啟 settings.py, 首先找到 Application definition 區段, 在 INSTALLED_APPS 串列末端添加上面新增的 demo 應用程式 :
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'demo',
]
同時將此區段之 TEMPLATES 串列中的 DIRS 屬性值由預設之空串列改為 [BASE_DIR / 'templates'], 這樣 Django 渲染網頁時才知道網頁模板在哪裡 :
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'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',
],
},
},
]
其次是將 Internationalization 區段的語言 (LANGUAGE_CODE) 與時區 (TIME_ZONE) 變數值改為繁體中文 (zh-Hant) 與台灣時區 (Asia/Taipei) :
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'zh-Hant'
TIME_ZONE = 'Asia/Taipei'
USE_I18N = True
USE_TZ = True
最後在最底下的 Static files 區段中, 於 STATIC_URL 變數底下添加一個 STATICFILES_DIRS 串列來指定靜態目錄之絕對路徑 :
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static',]
修改完畢將 settings.py 存檔.
7. 請求處理與路由分派 :
Django 對控制邏輯提供了彈性的選擇, 可視專案複雜度來選擇請求處理與路由分派的配置模式, 簡單的專案可以直接在下層專案目錄中自行添加請求處理器 views.py 即可; 複雜的專案則可以採用專案路由器 (建立專案時會自動產生) 與 App 路由器 (新增 App 時不會自動產生, 需自行建立) 分離的結構, 這樣做的好處是 App 與專案的耦合度 App 低 (可插拔設計), 可方便移植到別的專案中使用.
具體作法是在 App 目錄下自行建立 App 自己的路由器 urls.py 來分派屬於此 App 的請求給自己的請求處理器 views.py, 然後在專案路由器中用 django.urls.include() 將該 App 的路由器含括進來, 這樣專案路由器的內容就很清爽, 可一目了然看出專案內有哪些 App; 當 App 要移植到別的專案中使用時只要將 App 目錄複製過去, 然後於新專案的專案路由器中 include 該 App 的路由器即可, 架構如下圖所示 :
搭配此架構的 RESTful 風格網址結構如下 :
Protocol://Host address/AppName/AppURL/param1/param2/param3...
協定 (Protocol) 為 http 或 https, 主機位址是 IP (例如 127.0.0.1) 或域名 (localhost, www.abc.com 等), 接下來是 App 名稱與 App 位址 (在 App 的 urls.py 中映射到 views.py 中的函式名稱), 最後跟著的是參數群 (可有可無).
RESTful 網址會由左至右被一層一層剝掉 (striping), 當 HTTP 伺服器收到請求時, 首先協定與位址會先被伺服器剝除, 剩下 AppName/AppURL/param1/param2/param3... 被送到 Django 的專案路由器處理, 它會在取出 AppName 後將剩下的路徑送給該 App 的路由器, 然後取出的 AppURL (圖中的 url1) 會被映射到 views.py 中的函數 fun1 處理 (同時也會將參數群傳入該函數) :
參考 :
8. 編輯 App 的請求處理器 views.py :
上面建立應用程式 demo 時, 會在 demo 目錄下自動建立一個請求處理器 views.py, 它負責處理路由器 urls.py 所分派的請求, 執行特定邏輯產生回應給客戶端, 其預設內容僅有匯入 django.shortcuys.render() 函式一行而已, 此 render() 函式用來透過模板來渲染網頁 :
from django.shortcuts import render
# Create your views here.
我們需在此定義函式, 撰寫運算邏輯以便產生回應, 例如在瀏覽器輸入網址 http://127.0.0.1:8000/demo/hello/Tony 就會回應 'Hello Tony, 現在時間是 2025-09-05 12:30:00' 的 views.py 可以這麼寫 :
# views.py of App=demo
from django.shortcuts import render
from datetime import datetime
def hello(request, name):
now=datetime.now()
params={'name': name, 'now': now}
return render(request, 'hello.htm', params)
此函式 hello() 預設接收 request 物件參數, 後面可接收任意多的網址參數 (此處為 name), 將 name 參數與日期時間組成字典後傳給 render(), 指定由網頁模板 hello.htm 來取得此參數並渲染回應網頁. 此網頁可以繼承上面的 easyui.htm 模板來簡化結構 :
<!-- hello.htm -->
{% extends "easyui.htm" %}
{% block body %}
<--! 網頁內容寫在下面 -->
<p class="msg">Hello, {{ name }}, 現在的時間是 {{ now }}</p>
{% endblock %}
將此 hello.htm 存入 templates 目錄下即可.
9. 編輯 App 路由器 urls.py :
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
可見 urlpatterns 串列中預設只有管理應用程式 admin 而已.
由於新增 App 時 Django 並不會自動為 App 建立自己的路由器 (因為配置方式是可自訂的), 所以先將專案路由器 urls.py 複製到 App 目錄下編輯, 保留 path 並去除屬於專案的 admin 部分, 添加從 App=demo 匯入 views 模組, 內容修改如下 :
# urls.py of App=demo
from django.urls import path
from demo import views
app_name="demo"
urlpatterns = [
path('hello/<name>/', views.hello),
]
此處 app_name 就是 RESTful 網址中的 AppName 層, 而 path() 則是將去除 AppName 後的路徑 hello/<name>/ 指派給 views.py 中的 hello() 函式處理.
10. 編輯專案路由器 urls.py :
最後來編輯位於下層專案目錄 easyuicms 下的專案路由器 urls.py, 如上所述, 我們需要會匯入 django.urls.include() 函式來把 App 的路由器含括進來, 修改如下 :
# urls.py of Project=easyuicms
from django.contrib import admin
from django.urls import path
from django.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
path('demo/', include('demo.urls')),
]
此處 path() 的第一參數就是 RESTful 網址中的 AppName (後面須加斜線), 第二參數用 django.urls.include() 函式把 App 路由器含括進來, 也就是專案路由器不直接處理 demo 路徑的請求, 而是交由 App=demo 自行分派, 這樣專案路由器本身就不會亂糟糟, 而且可清楚知道此專案有哪些 App.
最後用 tree 指令檢視整個目錄結構 :
D:\django>tree easyuicms /f
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\DJANGO\EASYUICMS
│ db.sqlite3
│ manage.py
│
├─demo
│ │ admin.py
│ │ apps.py
│ │ models.py
│ │ tests.py
│ │ urls.py
│ │ views.py
│ │ __init__.py
│ │
│ └─migrations
│ __init__.py
│
├─easyuicms
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-310.pyc
│ urls.cpython-310.pyc
│ wsgi.cpython-310.pyc
│ __init__.cpython-310.pyc
│
├─static
│ ├─images
│ ├─js
│ │ │ jquery.easyui.min.js
│ │ │ jquery.min.js
│ │ │
│ │ └─locale
│ │ easyui-lang-zh_TW.js
│ │
│ └─themes
│ │ icon.css
│ │
│ └─default
│ easyui.css
│
└─templates
base.htm
demo.htm
easyui.htm
hello.py
這樣就完成所有網站配置了.
11. 做 migration 與啟動開發伺服器 :
在前一篇測試中啟動瀏覽器時會出現與資料庫同步有關的 "migration" 訊息, 雖然目前還沒有用到資料庫, 但還是按步驟先用下列指令建立資料庫 migration 資料檔, 並與資料庫同步 :
python manage.py makemigrations (建立遷移檔)
python manage.py migrate (與資料庫同步)
D:\django\easyuicms>python manage.py makemigrations
No changes detected
D:\django\easyuicms>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
這樣在啟動開發伺服器時就不會出現要做 "migration" 的提醒了 :
D:\django\easyuicms>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
September 05, 2025 - 13:51:09
Django version 4.2.4, using settings 'easyuicms.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
瀏覽下列網址就可以看到上面配置之結果網頁了 :
# http://127.0.0.1:8000/demo/hello/Tony/
以上測試的整個專案放在 GitHub :



沒有留言 :
張貼留言