Django CRUD 的 R(Read):資料讀取與顯示功能指南

更新日期: 2024 年 12 月 2 日

Django 的 CRUD:R(Read) 功能主要用於從資料庫讀取資料並展示給用戶。

本篇將帶你通過實例完成資料列表顯示和單筆資料的查看,並詳細解釋路由設計與動態 URL 的生成過程。


專案目錄結構

完成資料讀取功能後,專案目錄應如下:

mysite/
├── manage.py
├── mysite/
   ├── settings.py       # 專案配置文件
   ├── urls.py           # 主路由配置

├── resumes/
   ├── __init__.py
   ├── admin.py
   ├── apps.py
   ├── models.py         # 定義 Resume 模型
   ├── views.py          # 定義新增資料與處理邏輯
   ├── urls.py           # 配置應用的路由
   ├── templates/
       ├── resumes/
           ├── home.html  # 顯示 Resume 列表
           ├── show.html  # 顯示單筆資料
           ├── new.html   # 新增資料表單
├── db.sqlite3            # SQLite 資料庫

配置路由與視圖

resumes/urls.py 中定義路由:

from django.urls import path
from . import views

app_name = 'resumes'  # 定義 namespace,供模板生成動態路徑使用

urlpatterns = [
    path("", views.home, name='list'),       # 主頁,顯示所有資料
    path("<int:id>/", views.show, name="show"),  # 顯示單筆資料
    path("new/", views.new, name='nn')       # 新增資料頁面
]

在 Django 的 urls.py 中,<int:id> 是一種 路徑轉換器 (path converter),其作用是:

  1. <> 是表示變數的佔位符
    • 它允許在 URL 模式中定義一個動態部分。
    • 動態部分的值會被提取並傳遞給對應的視圖函數作為參數。
  2. int 是轉換器的類型
    • 指定這個動態部分必須是一個整數。
    • 如果 URL 中的值不是整數(例如字母或特殊符號),Django 會自動返回一個 404 錯誤。
  3. id 是變數名稱
    • 當匹配這個 URL 模式時,Django 會提取動態部分的值並賦值給 id
    • 然後將該值作為參數傳遞給對應的視圖函數。

具體說明

path("<int:id>/", views.show, name="show")
  • 如果訪問的 URL 是 /123/,Django 會:
    • 提取 123,並確認它是整數。
    • 123 傳遞給 views.show 作為 id 的值。

對應的視圖函數可能像這樣:

from django.http import HttpResponse

def show(request, id):
    return HttpResponse(f"您請求的資料 ID 是: {id}")

當訪問 /123/ 時,瀏覽器將顯示:

您請求的資料 ID 是: 123

可用的路徑轉換器類型

Django 提供了幾種內建的路徑轉換器,您可以根據需求選擇:

  • str:匹配任何非空字符串(預設類型)。
  • int:匹配正負整數。
  • slug:匹配字母、數字、連字號和下劃線。
  • uuid:匹配一個 UUID。
  • path:匹配路徑,包括斜槓。

範例:

path("<str:name>/", views.greet, name="greet"),
path("<slug:slug>/", views.article, name="article"),
path("<uuid:identifier>/", views.item, name="item"),

這些路徑轉換器讓 Django 的 URL 配置變得更靈活,也能使代碼更具可讀性和結構化。


配置視圖

主頁視圖:顯示資料列表

resumes/views.py 中定義首頁的邏輯,用於顯示所有資料:

from django.shortcuts import render
from .models import Resume

def home(request):
    # 讀取所有 Resume 資料
    resumes = Resume.objects.all()
    return render(
        request,
        "resumes/home.html",
        {"resumes": resumes}
    )

逐行解析:

  1. resumes = Resume.objects.all()
    • 查詢 Resume 模型中的所有資料,返回一個 QuerySet(類似列表的物件)。
    • QuerySet 包含每一筆資料的實例,這些實例對應資料庫中的記錄。
  2. return render()
    • "resumes/home.html":指定渲染的模板。
    • {"resumes": resumes}:將 QuerySet 以字典的形式傳遞給模板,鍵為 resumes,值為查詢結果。
    • 模板可以通過 {% for resume in resumes %} 迴圈讀取資料。

補充說明:MyModel.objects.all()

MyModel.objects.all() 是 Django 框架中特有的語法。

在 Django 中,每個模型類別(例如 MyModel)都自動擁有一個名為 objects 的管理器(Manager),該管理器提供了多種方法來查詢資料庫。

其中,all() 方法用於獲取該模型在資料庫中的所有記錄,並返回一個 QuerySet 物件。

這種設計,使得開發者能夠以簡潔且直觀的方式進行資料庫操作,而無需直接撰寫 SQL 查詢。

例如,MyModel.objects.all() 會生成一個 SELECT 查詢,檢索 MyModel 對應資料表中的所有記錄。

相當於:

select * from table

需要注意的是,這種語法是 Django 的特性,在其他 Python 框架或純 Python 環境中並不存在。

因此,若在非 Django 環境中使用 MyModel.objects.all(),會導致錯誤。

單筆資料視圖:顯示指定 ID 的資料

resumes/views.py 中定義單筆資料的查看邏輯:

from django.shortcuts import render, get_object_or_404
from .models import Resume

def show(request, id):
    # 若資料不存在,返回 404 錯誤
    resume = get_object_or_404(Resume, id=id)
    return render(
        request,
        "resumes/show.html",
        {"resume": resume}
    )

逐行解析:

  1. resume = get_object_or_404(Resume, id=id)
    • 嘗試從 Resume 模型中查詢主鍵為 id 的資料。
    • 如果資料存在,返回對應的物件;如果不存在,自動返回 404 錯誤頁面。
  2. return render()
    • "resumes/show.html":指定渲染的模板。
    • {"resume": resume}:將查詢結果以字典的形式傳遞給模板。

設置資料列表模板:home.html

在首頁顯示資料列表,並為每筆資料添加超連結:

{% extends "shared/layout.html" %}

{% block content %}
<h1>Resume 首頁</h1>
<a href="{% url 'resumes:nn' %}">新增 Resume</a>

<ul>
{% for resume in resumes %}
    <li>
        <a href="{% url 'resumes:show' resume.id %}">{{ resume.title }}</a>
    </li>
{% endfor %}
</ul>
{% endblock %}

解析 {% url ‘resumes:show’ resume.id %}

在 Django 模板中,{% url %} 是用來生成動態路徑的標籤。

以下是該標籤 {% url 'resumes:show' resume.id %} 生成超連結的具體解析,與對應代碼的詳細說明:

'resumes:show' 表示路由的名稱空間和名稱

路由的名稱空間

resumes,定義在應用的 urls.py 中,通過以下代碼設定:

# resumes/urls.py
app_name = 'resumes'

這使得該應用的路由擁有命名空間,便於與其他應用的路由區分。

路由的名稱

show,對應以下路由定義:

# resumes/urls.py
urlpatterns = [
    path("<int:id>/", views.show, name="show"),  # 單筆資料的路由
]

該路由中,<int:id> 是路徑參數,用於捕獲 URL 中的整數值。

name="show" 時,該路由可以被引用為 resumes:show

模板中的 resume.id:主鍵與資料來源解析

在 Django 的模板中,resume.id 是單筆資料的主鍵,對應於資料庫中 Resume 模型的 id 欄位。

以下將詳細說明 resumeresumes 的來源及其在模板中的使用。

resumes 的來源:從視圖到模板的傳遞

  • 定義視圖函數
    views.py 中,我們定義了 home 函數,負責處理主頁請求,查詢資料並將結果傳遞到模板。
    具體代碼如下:
# resumes/views.py
from django.shortcuts import render
from .models import Resume

def home(request):
    resumes = Resume.objects.all()  # 取得所有資料
    return render(request, "resumes/home.html", {"resumes": resumes})
  • 逐行解釋
    1. Resume.objects.all()
      • 查詢資料庫: 該方法調用 Django ORM,查詢資料庫中 Resume 模型的所有記錄。
      • 返回結果: 返回一個 QuerySet,它是一個類似列表的物件,包含多筆資料,每筆資料對應於資料庫中的一條記錄。
      • 用途: 這些資料將在模板中被渲染,展示給用戶。
    2. {"resumes": resumes}
      • 上下文傳遞: 使用 Python 字典將查詢結果 resumes 作為上下文數據傳遞給模板。
      • 模板變數: 在模板中,resumes 變數即代表 QuerySet,包含所有 Resume 資料。

resume 的來源:模板中的迴圈變數

在模板中,resume 是通過 Django 模板語法 {% for resume in resumes %} 定義的迴圈變數。

以下為模板範例代碼:

{% extends "shared/layout.html" %}

{% block content %}
<h1>Resume 列表</h1>
<ul>
    {% for resume in resumes %}
        <li>
            <a href="{% url 'resumes:show' resume.id %}">{{ resume.title }}</a>
        </li>
    {% endfor %}
</ul>
{% endblock %}
  • 逐行解析
    1. {% for resume in resumes %}
      • 迴圈變數: 將 resumes(從視圖傳遞的 QuerySet)中的每一筆資料逐一取出,賦值給 resume
        • 每次迴圈,resume 代表 QuerySet 中的一個物件,對應於資料庫中的一條記錄。
    2. resume.id
      • 主鍵idresume 的屬性,對應於資料庫中該記錄的主鍵欄位。
    3. {% url 'resumes:show' resume.id %}
      • 動態生成 URL,用於指向單筆資料的詳細頁面(如 /resumes/1/)。

resume.id 的角色:資料庫記錄的主鍵

  • 定義
    • resume.idResume 模型的主鍵(Primary Key),由 Django 自動生成。
    • 主鍵唯一標識每一筆資料,方便在應用中進行資料操作(如讀取、更新或刪除)。
  • 資料結構對應
    假設資料庫中有以下記錄:
    • 第一次迴圈時,resume 對應於 id=1 的記錄。
    • 第二次迴圈時,resume 對應於 id=2 的記錄。
+----+-------------+----------+-----------+
| id | title       | skill    | content   |
+----+-------------+----------+-----------+
| 1  | Developer   | Python   | Backend   |
| 2  | Designer    | Photoshop| UI/UX     |
+----+-------------+----------+-----------+
  • 實際應用: 在模板中,我們可以透過 resume.id 指向詳細頁:
<a href="{% url 'resumes:show' resume.id %}">{{ resume.title }}</a>
  • 生成的超連結如下:
<a href="/resumes/1/">Developer</a>
<a href="/resumes/2/">Designer</a>

完整運作流程

  1. 資料庫查詢
    • 使用 Resume.objects.all() 查詢所有 Resume 資料,返回 QuerySet。
  2. 上下文傳遞
    • 將 QuerySet 封裝成字典,作為上下文傳遞到模板中。
  3. 模板渲染
    • 在模板中,通過 {% for resume in resumes %} 迴圈遍歷 QuerySet。
  4. 生成超連結
    • 使用 resume.id 動態生成超連結,指向每筆資料的詳細頁面。

補充:{% url %} 的動態生成

當你在 Django 模板中使用動態模板標籤 {% url %} 時,它的主要作用是 動態生成 URL,避免在模板中硬編碼靜態路徑。

這樣做有以下好處:

  • 方便管理:如果 URL 改變,只需在 urls.py 中更新即可,模板中會自動更新。
  • 減少出錯:避免在多處模板中直接硬編碼 URL,降低出錯風險。
  • 支持多應用:利用命名空間(app_name)支持跨應用路徑生成。
基本語法
{% url '命名空間:路徑名稱' 參數1 參數2 ... %}
  • 命名空間
    • 對應 urls.py 中的 app_name
    • 幫助在多應用中區分 URL,例如:resumes:show
  • 路徑名稱
    • 對應 urlpatterns 中的 name='...'
    • 用於識別特定的路徑配置。
  • 參數
    • 如果路徑定義中包含動態部分(例如 <int:id>),則這裡需要傳入對應的值。

Django 的 URL 配置並不是簡單地將 app_name:路徑名稱 和參數拼接在一起,而是依賴於 urls.py 中的 urlpatterns 定義 來動態解析 URL。

{% url %} 的解析過程

當模板中使用 {% url 'resumes:show' resume.id %} 時,Django 會執行以下步驟:

  1. 找到命名空間
    • resumesapp_name,表示這段 URL 屬於 resumes 應用。
  2. 匹配路徑名稱
    • showurlpatterns 中的 name='show',Django 會定位到以下這段定義:
path('<int:id>/', views.show, name='show')
  1. 解析路徑參數
    • <int:id> 定義了路徑中需要的動態參數 id
    • resume.id 的值(假設為 123)會被填入 <int:id> 的佔位符中。
  2. 生成 URL
    • 根據 path('<int:id>/', ...),生成的路徑是 /123/

單筆資料模板:show.html

resumes/templates/resumes/show.html 中設置單筆資料的顯示邏輯:

{% extends "shared/layout.html" %}

{% block content %}
<h1>{{ resume.title }}</h1>
<h3>{{ resume.skill }}</h3>
<article>
    <p>{{ resume.content }}</p>
</article>
{% endblock %}

代碼解析

  1. {{ resume.title }}:顯示該筆資料的 title 屬性。
  2. {{ resume.skill }}:顯示該筆資料的 skill 屬性。
  3. {{ resume.content }}:顯示該筆資料的 content 屬性。

小結

通過以上步驟,我們完成了 Django CRUD 的 R(Read)功能:

  1. 顯示資料列表:在首頁模板中使用迴圈遍歷資料,並為每筆資料生成動態超連結。
  2. 顯示單筆資料:根據 URL 中的動態 ID 查詢資料並顯示詳細內容。
  3. RESTful 設計:通過動態路由設計實現清晰的資源定位,符合 RESTful API 的標準。

這套資料讀取功能為後續的資料操作(更新與刪除)奠定了堅實基礎!

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *