2023年10月20日 星期五

Python 學習筆記 : Django 4 用法整理 (三) 靜態檔案

今天繼續整理 Django 4 的用法, 本次複習的前兩篇筆記參考 :


本篇延續前一篇網頁模板的架構, 在此基礎上添加靜態檔案, 例如圖片, 影片, CSS 樣式表, 與 Javascript 程式檔等, 這些資源大部分可以透過 CDN 或從第三方網址載入到客戶端以節省伺服器空間, 但有些情況下必須由網站本身提供 (例如封閉環境無法使用 Internet 或為了使用特定版本的網頁框架等). 

以下測試參考了之前的筆記 :



一. 編輯專案設定檔 settings.py : 

Django 的靜態檔案可以放在 App 目錄下, 也可以放在上層專案目錄下 (需設定 STATICFILES_DIRS 變數). 

首先開啟下層專案目錄 mysite 下的設定檔 settings.py 檢查 INSTALLED_APPS 變數, 看看是否已安裝 django.contrib.staticfiles 這個 App (Django 4 預設已安裝) :

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp1',
]

有了 django.contrib.staticfiles 這個 App 就可以在模板網頁中使用 {% load static %} 與 {% static %} 等靜態檔案指令. 

其次檢查 settings.py 的靜態檔案資料夾名稱變數 STATIC_URL 設定 (預設值為 'static/'): 

STATIC_URL = 'static/' 

這表示 Django 預設會到各 App 目錄底下的 static 資料夾尋找靜態檔案資源. 

如果靜態檔案是放在其他位置 (例如上層專案目錄下的 static), 就必須添加一個 STATICFILES_DIRS 變數來指定, 此變數是一個串列, 只要將靜態檔案目錄之路徑放入串列中即可, 例如上層專案目錄的 static 資料夾位置指定方式如下 : 

STATICFILES_DIRS = [
    BASE_DIR / 'static',
]

其中 BASE_DIR 為網站根目錄 (即上層專案目錄) 絕對位置. 注意, 以前在 Django 2 必須用 os.path.join() 函式將 BASE_DIR 與 'static' 組合起來, 在 Django 4 已經不需要了, 用 / 直接將兩者串起來即可. 

參考官網教學文件 :


在模板網頁中使用靜態檔案之前必須先用下列模板指令載入靜態檔案路徑 (通常放在 head 標籤內匯入 CSS 與 Javascript 之前) : 

{% load static %} 

注意, 在 Django 2 版使用的 {% load staticfiles %} 在 Django 3 版後已不再使用, 改用 {% load static %} 指令. 然後即可用下列模板指令格式載入靜態檔案資源 : 

{% static "靜態檔檔名" %}

注意, 如果靜態檔案是放在 static 的子目錄下, 則必須加上路徑, 例如放在 static/images/ 下的  ok.jpg 要寫成 {% static "images/ok.jpg" %}. 


二. 建立靜態檔案資料夾 static : 

首先從上一篇測試文章 "Python 學習筆記 : Django 4 用法整理 (二) 網頁模板" 下載模板網頁範例來進行修改 :


在上層專案目錄 mysite 底下建立專案靜態檔案資料夾 static (與 App 資料夾平行), 但常用的靜態檔案有圖片, 樣式與程式檔, 全部混在一起很亂, 通常會在 static 下再建立 images, css, 與 js 三個子目錄用來分別存放上面三種常用的靜態檔案, 

建立好專案靜態資料夾 static 後, 將其複製一份到 myapp1 底下 :

mysite\ (上層專案目錄)
     |____ manage.py
     |____ db.sqlite3
     |____ mysite\  (下層專案目錄)
     |              |____ __init__.py
     |              |____ settings.py
     |              |____ urls.py
     |              |____ views.py  (自行添加)
     |              |____ wsgi.py
     |____ templates\ (網頁模板目錄)
     |              |____ home.htm  (網站首頁)
     |____ static\        (網站靜態檔案目錄)
     |              |____ images\
     |              |____ css\
     |              |____ js\
     |____ myapp1\                     (應用程式目錄)
                  |____ migrations\    (資料庫同步)
                   |____ __init__.py    (形成套件)
                 |____ admin.py       (註冊資料模型)
                 |____ apps.py         (App 設定檔)
                 |____ models.py     (資料模型定義)
                 |____ tests.py          (測試用程式)
                 |____ views.py        (App 視圖模組, 自動建立)
                 |____ urls.py           (App 路由模組, 手工添加)
                 |____ templates\     (網頁模板目錄)
                 |             |____ hello.htm  
                 |             |____ myapp1_home.htm  (App 首頁)  
                   |____ static\               (App 靜態檔案目錄)
                                   |____ images\
                                   |____ css\
                                   |____ js\


三. 載入圖檔 : 

首先準備兩個表示 Home 的圖檔來測試能否成功匯入靜態圖檔資源, 第一張是要放在專案網站首頁中的圖檔 home.png : 





下載後將其更名為 home.png 存放到上層專案目錄 mysite 的 static/images 下.

另一張圖則是要給 myapp1 的 App 首頁 myapp1_home.htm 用的 :


原圖解析度為 512x512, 先用 Picpick 轉成跟上面的 home.png 相同的 125x125, 更名為 myapp1_home.png, 存放於 myapp1/static/images 下 : 




此例網站架構圖如下 : 

mysite\ (上層專案目錄)
     |____ manage.py
     |____ db.sqlite3
     |____ mysite\  (下層專案目錄)
     |              |____ __init__.py
     |              |____ settings.py
     |              |____ urls.py
     |              |____ views.py  (自行添加)
     |              |____ wsgi.py
     |____ templates\ (網頁模板目錄)
     |              |____ home.htm  (網站首頁)
     |____ static\        (網站靜態檔案目錄)
     |              |____ images\
     |              |            |____ home.png   
     |              |____ css\
     |              |____ js\
     |____ myapp1\                     (應用程式目錄)
                  |____ migrations\    (資料庫同步)
                   |____ __init__.py    (形成套件)
                 |____ admin.py       (註冊資料模型)
                 |____ apps.py         (App 設定檔)
                 |____ models.py     (資料模型定義)
                 |____ tests.py          (測試用程式)
                 |____ views.py        (App 視圖模組, 自動建立)
                 |____ urls.py           (App 路由模組, 手工添加)
                 |____ templates\     (網頁模板目錄)
                 |             |____ hello.htm  
                 |             |____ myapp1_home.htm  (App 首頁)  
                   |____ static\               (App 靜態檔案目錄)
                                   |____ images\
                                   |             |____ myapp1_home.png   
                                   |____ css\
                                   |____ js\
 
首先修改專案網頁模板資料夾 templates 下的網站首頁 home.htm, 在上面添加靜態檔案資源 : 

<!-- home.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>首頁</title>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  {% load static %}   
</head>
<body>
  <h4>歡迎來到我的首頁! 現在的時間是 {{now}}</h4>
  <img src="{% static "images/home.png" %}">
  <p><a href="/myapp1">到 myapp1</a></p>
</body>
</html>

其中 {% load static %} 指令只要在 {% static "靜態檔檔名" %} 之前即可, 通常是放在 head 標籤內. 圖檔底下多了一個前往 myapp1 首頁的超連結. 

其次編輯 myapp1/templates 下的 App 首頁檔 myapp1_home.htm :

<!-- myapp1_home.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  {% load static %}   
</head>
<body>
  <h4>這是 App1 首頁!</h4>
  <img src="{% static "images/myapp1_home.png" %}" alt="回首頁">
  <p><a href="/">回網站首頁</a></p>
</body>
</html>

注意, 此處載入的圖片是 myapp1 的 static 子目錄 images 下的 myapp1_home.png. 存檔後在上層專案目錄下用 python manage.py runserver 啟動測試伺服器, 然後瀏覽 127.0.0.1:8000 即可看到網站首頁 home.htm 會載入圖檔 : 




按底下的 '到 myapp1' 超連結就會顯示 myapp1 的首頁 : 



可見圖檔不論是位於專案還是 App 的 static 資料夾內都能正確地載入網頁中. 

以上測試之網站資料可從 GitHub 下載 : 



四. 載入 CSS 與 Javascript 檔 : 

這兩種靜態檔載入方式與上面的圖檔類似, 只要將 .css 與 .js 檔分別放入 static/css 與 static/js 資料夾下面即可. 以下使用上面範例中 myapp1 的 hello.htm 模板來測試 css 與 js 靜態檔案的載入, 先準備下面兩個檔案 :

/* hello.css  */
.msg {
  font-weight: bold;
  text-shadow: navy 3px 3px 3px;
  }

此 hello.css 放在 myapp1/static/css 資料夾下面. 

/* hello.js */
alert("Hello!");

此 hello.js 放在 myapp1/static/js 資料夾下面.

這是之前測試 Django 2 時所用的簡單範例, 參考 :


此例網站架構圖如下 : 

mysite\ (上層專案目錄)
     |____ manage.py
     |____ db.sqlite3
     |____ mysite\  (下層專案目錄)
     |              |____ __init__.py
     |              |____ settings.py
     |              |____ urls.py
     |              |____ views.py  (自行添加)
     |              |____ wsgi.py
     |____ templates\ (網頁模板目錄)
     |              |____ home.htm  (網站首頁)
     |____ static\        (網站靜態檔案目錄)
     |              |____ images\
     |              |            |____ home.png
     |              |____ css\
     |              |____ js\
     |____ myapp1\                     (應用程式目錄)
                  |____ migrations\    (資料庫同步)
                   |____ __init__.py    (形成套件)
                 |____ admin.py       (註冊資料模型)
                 |____ apps.py         (App 設定檔)
                 |____ models.py     (資料模型定義)
                 |____ tests.py          (測試用程式)
                 |____ views.py        (App 視圖模組, 自動建立)
                 |____ urls.py           (App 路由模組, 手工添加)
                 |____ templates\     (網頁模板目錄)
                 |             |____ hello.htm  
                 |             |____ myapp1_home.htm  (App 首頁)  
                   |____ static\               (App 靜態檔案目錄)
                                   |____ images\
                                   |             |____ myapp1_home.png
                                   |____ css\
                                   |             |____ hello.css  
                                   |____ js\
                                                 |____ hello.js   

然後修改 myapp1/templates 底下的模板網頁 hello.htm, 先利用模板指令載入兩個靜態檔案 (藍色粗體部分), 然後在顯示招呼語的 h4 標籤上添加 class='msg' 樣式 : 

<!-- hello.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  {% load static %}  
  <link rel="stylesheet" href="{% static "css/hello.css" %}">
  <script src="{% static "js/hello.js" %}"></script>
</head>
<body>
  <h4 class="msg">Hello, {{name}}, 現在的時間是 {{now}}</h4>
</body>
</html>

這樣就完成全部配置了, 這時瀏覽 127.0.0.1:8000/myapp1/hello/Tony 會因為執行載入的 hello.js 而先跳出一個 'Hello!' 提示視窗, 關掉後再套用載入的 hello.css 顯示字型的陰影效果 : 



可見載入的 js 檔有被執行, css 檔的樣式也套用到 h4 的招呼語上了. 

以上測試範例可從 GitHub 下載 : 


最後來測試能否從上層專案目錄 mysite 下的 static 資料夾載入 css 與 js 檔, 將前面範例的 hello.css 複製到 mysite/static/css 下, 改名為 welcome.css, 內容不變 : 

/* welcome.css  */
.msg {
  font-weight: bold;
  text-shadow: navy 3px 3px 3px;
  }

將前面範例的 hello.css 複製到 mysite/static/js 下, 改名為 welcome.js, 內容則是將 alert() 的傳入參數改為 'Welcome!' :

/* welcome.js */
alert("Welcome!");

此例網站架構圖如下 : 

mysite\ (上層專案目錄)
     |____ manage.py
     |____ db.sqlite3
     |____ mysite\  (下層專案目錄)
     |              |____ __init__.py
     |              |____ settings.py
     |              |____ urls.py
     |              |____ views.py  (自行添加)
     |              |____ wsgi.py
     |____ templates\ (網頁模板目錄)
     |              |____ home.htm  (網站首頁)
     |____ static\        (網站靜態檔案目錄)
     |              |____ images\
     |              |            |____ home.[ng
     |              |____ css\
     |              |            |____ welcome.css    
     |              |____ js\
     |                           |____ welcome.js   
     |____ myapp1\                     (應用程式目錄)
                  |____ migrations\    (資料庫同步)
                   |____ __init__.py    (形成套件)
                 |____ admin.py       (註冊資料模型)
                 |____ apps.py         (App 設定檔)
                 |____ models.py     (資料模型定義)
                 |____ tests.py          (測試用程式)
                 |____ views.py        (App 視圖模組, 自動建立)
                 |____ urls.py           (App 路由模組, 手工添加)
                 |____ templates\     (網頁模板目錄)
                 |             |____ hello.htm  
                 |             |____ myapp1_home.htm  (App 首頁)  
                   |____ static\               (App 靜態檔案目錄)
                                   |____ images\
                                   |             |____ myapp1_home.png
                                   |____ css\
                                   |             |____ hello.css
                                   |____ js\
                                                 |____ hello.js

最後修改網站首頁模板 home.htm, 加上模板指令載入 css 與 js 靜態檔案, 並替 h4 標籤加上 class="msg" 以便讓首頁歡迎語套上 welcome.css 中的 msg 樣式類別 :

<!-- home.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>首頁</title>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  {% load static %}
  <link rel="stylesheet" href="{% static "css/welcome.css" %}">
  <script src="{% static "js/welcome.js" %}"></script>
</head>
<body>
  <h4 class="msg">歡迎來到我的首頁! 現在的時間是 {{now}}</h4>
  <img src='{% static "images/home.png" %}'>
  <p><a href="/myapp1">到 myapp1</a></p>
</body>
</html>

這時瀏覽 127.0.0.1:8000/ 會因為執行載入的 welcome.js 而先跳出一個 'Welcome!' 提示視窗, 關掉提示後再套用載入的 welcome.css 而顯示字型的陰影效果 :




此測試範例可從 GitHub 下載 : 


沒有留言 :