在 Django 框架中,Model 是用來表示資料庫資料的 Python 類別,透過 ORM(物件關聯對應)技術,讓開發者可以用 Python 語法操作資料表。每個 Model 對應一張資料表,類別屬性對應欄位,欄位可設定型別與限制,如 CharField、IntegerField、max_length、null 等。Django 支援資料表之間的關聯,例如一對多(ForeignKey)、一對一(OneToOneField)、多對多(ManyToManyField),讓資料關聯清晰易懂。開發者可以透過 ORM 提供的 API 來新增、查詢、更新、刪除資料,無需寫 SQL。當模型變更時,Django 提供 Migrations 機制來同步資料庫結構。Models 也可以自定義方法、屬性,或透過 Meta 類別設定排序與表名等細節。只要註冊 Model 到 Django 管理後台,就能快速產生完整的資料管理介面。綜合上述,Django 的 Model 系統以簡潔、可讀性高且功能強大的設計,提供開發者一套有效率且穩定的資料庫操作方式。
1. 你建立的第一個 Model
以下程式碼是在 02.Django 4 快速搭建網站 文章中建立一個資料表的程式碼:
1 | class Post(models.Model): |
對應語法說明:
1 | class <資料表名稱>(models.Model): |
2. 欄位型態與屬性設定
2.1 常見欄位型態
欄位格式 | 參數 | 說明 |
---|---|---|
BigIntegerField | 64位元之大整數 | |
BooleanField | 布林值,只有True/False兩種 | |
CharField | max_length:指定可接受之字串長度 | 用來儲存較短資料的字串,通常使用於單行的文字資料 |
DateField | auto_now:每次物件被儲存時即自動加入目前日期 auto_now_add:只有在物件被建立時才加入目前日期 | 日期格式,可用於datetime.date |
DateTimeField | 同上 | 日期時間格式,對應到datetime.datetime |
DecimalField | max_digits:可接受的最大位數 decimal_places:在所有的位數中,小數佔幾個位數 | 定點小數數值資料,適用於Python的Decimal模組之實例 |
FloatField | 浮點數欄位 | |
IntegerField | 整數欄位,是通用性最高的整數格式 | |
PostiveIntegerField | 正整數欄位 | |
SlugField | max_length:最大字元長度 | 和CharField是一樣的,通常用來當做是網址的一部份 |
TextField | 長文字格式,一般是用在HTML表單中的Textarea輸入項目 | |
URLField | max_length:最大字元長度 | 和CharField是一樣的,特別用來記錄完整的URL網址 |
DecimalField | 64位元之大整數 |
其他詳細欄位說明請參考官方文件
2.2 常見欄位選項
欄位格式 | 說明 |
---|---|
null | 此欄位是否接受儲存空值NULL,預設值是False |
blank | 此欄位是否接受儲存空白內容,預設值是False |
choices | 以選項的方式(只有固定內容的資料可以選用)當做是此欄位的侯選值 |
default | 輸入此欄位的預設值 |
help_text | 欄位的提示訊息 |
primary_key | 把此欄位設定為資料表中的主鍵KEY,預設值為False |
其他詳細欄位選項說明請參考官方文件
2.3 範例
1 | from django.db import models |
3. 建立與套用資料遷移(Migrations)
使用 Django 框架進行開發,當您新增或是修改模型後,必須透過「資料遷移 (Migrations)」,將資料庫中的資料表進行同步。
3.1 建立遷移檔案 (makemigrations)
1 | python manage.py makemigrations |
上面這一則指令,會根據所有 APP 底下 models.py
的更動,自動建立一個遷移檔案,紀錄哪些資料標的結構變化。執行成功後會出現類似以下訊息:
1 | Migrations for 'myapp': |
3.2 套用遷移檔案至資料庫 (migrate)
透過以下指令,將遷移的內容進行資料庫對應資料表的修改與變更。
1 | python manage.py migrate |
執行完成後會得到類似下面的提示訊息:
1 | Operations to perform: |
3.3 其他 Migrateions 相關指令
查看目前遷移狀態:
1 | python manage.py showmigrations |
指令特定的 APP 進行遷移:
1 | python manage.py makemigration <app:name> |
4. 使用 Django Shell 操作 Models
Djagno 提供互動式 Python 命令列介面 (Django Shell),可以直接透過 Django Models 進行存取資料庫的資料,進行新增、查詢、更新及刪除 (Create, Read, Update, Delete; CRUD) 操作,適合用來測試與偵錯。
4.1 進入 Django Shell
透過以下指令,進入互動式命令介面:
1 | python manage.py shell |
當終端機看到 Python 的互動式提示符號 (>>>
) 即可開始進行操作。
4.2 載入需要操作的模型
假設 posts/models.py
存在 Post
的模型,透過 Python import 語法,將其匯入至互動式介面:
1 | from posts.models import Post |
4.3 新增資料 (Create)
透過 create()
方法新增一筆資料:
1 | article = Post.objects.create( |
或者先建立實體再透過 save()
進行存入資料庫:
1 | article = Post( |
create()
與 save()
方式都可以使用,取決於使用的時機。
4.4 查詢(讀取)資料 (Read)
查詢所有資料:
1 | Post.objects.all() |
查詢特定條件 (filter):
1 | Post.objects.filter(content="Test for content ...") |
查詢單一紀錄 (get):
1 | Post.objects.get(slug="django-course-models") |
如果 get()
查詢到多筆或找不到資料時會拋出 error,建議使用 try/expect
處理。
欄位排序:
1 | Post.objects.order_by('-pub_date') |
模糊查詢:
1 | Post.objects.filter(content__icontains="django") |
4.5 更新資料 (Update)
1 | article = Post.objects.get(id=1) |
批次更新
1 | Post.objects.filter(content__icontains="django").update(title="Django 入門指南書") |
4.6 刪除資料 (Delete)
1 | article = Post.objects.get(id=1) |
批次刪除:
1 | Post.objects.filter(content__icontains="django").delete() |
4.7 其他常用的查詢處理
計算資料筆數:
1 | Post.objects.count() |
檢查資料是否存在:
1 | Post.objects.filter(title="Django 教學").exists() |
取得弟一筆資料:
1 | Post.objects.first() |
取得最新一筆資料(需 ordering):
1 | Book.objects.latest('published_date') |
5. 建立關聯模型(Relationships)
在 Django 中,模型之間常常需要建立關聯,以呈現資料之間的邏輯與結構關係。舉例來說,一個使用者可能撰寫多篇文章,而每篇文章則對應到一位作者,這種關聯關係在資料庫設計中非常常見。為了方便在程式中表示與操作這些關係,Django 提供了三種主要的關聯欄位類型,分別是 ForeignKey(一對多)、OneToOneField(一對一)以及 ManyToManyField(多對多),讓開發者能夠清楚且有效率地定義資料模型之間的關聯性。
5.1 ForeignKey
(一對多)
表示「多個紀錄」對應到「一個紀錄」。例如:多篇文章(Article)屬於同一位作者(Author)。
1 | class Author(models.Model): |
ForeignKey()
的第一個參數表示關聯的資料表,第二個參數表示級聯 (CASCADE),當被參照的資料被刪除時,參照資料也會一併刪除。使用案例:
1 | author = Author.objects.get(id=1) |
其中 article_set
為反查關聯的模型 (小寫模型名稱 + _set
)。
5.2 OneToOneField (一對一)
表示兩個模型之間為一對一關係,例如一個使用者對應一份個人資料(Profile)。
1 | class User(models.Model): |
1 | user = User.objects.get(id=1) |
5.3 ManyToManyField (多對多)
表示多個物件彼此互相關聯,例如:學生選課,學生與課程之間是多對多關係。
1 | class Student(models.Model): |
1 | # 取得某學生的所有課程 |
5.4 使用 related_name
逆向查詢
related_name
讓我們能更直覺地從關聯模型反向查詢。
範例(多對多):
1 | class Tag(models.Model): |
1 | tag = Tag.objects.get(name="Django") |
5.5 關聯查詢語法範例(ORM 實作)
5.5.1 正向查詢
1 | # 取得某篇文章的作者名字 |
5.5.2 反向查詢
1 | # 取得某位作者的所有文章 |
5.5.3 篩選關聯資料
1 | # 查詢某作者的所有文章(用 filter) |
5.5.4 多層關聯查詢
1 | # 查詢某課程的所有學生的名字 |
1 | # 查詢有標籤「Python」的所有文章 |
6. Meta
類別與自定義 Model 行為
在 Django 的模型中,可以透過 Meta
類別來定義一些模型的元資料(metadata),例如排序方式、資料表名稱、權限設定等。此外,我們也可以透過撰寫自定義方法來擴充模型的行為,例如 __str__()
方法顯示易讀的物件名稱,或加入自定義的查詢方法以提高開發效率。
6.1 Meta
類別自定義模型: 排序 (ordering
)
透過 ordering
屬性可以設定模型查詢結果的預設排序方式。
1 | class Article(models.Model): |
這樣當我們使用 Article.objects.all()
時,資料會依照發佈日期從新到舊排序。
6.2 Meta
類別自定義模型: 資料表名稱 (db_table
)
Django 預設會根據模型名稱自動建立資料表名,例如模型 Article
對應的資料表為 appname_article
。你可以使用 db_table
自定義資料表名稱:
1 | class Article(models.Model): |
6.3 Meta
類別自定義模型: 權限 (permissions
)
可以在 Meta
中自定義額外的權限,例如給特定角色額外操作的能力:
1 | class Report(models.Model): |
這些權限會在 auth_permission
表中建立,可以搭配 Django 的權限系統使用(如 admin 介面或 @permission_required
裝飾器)。
6.4 自定義模型方法: __str__()
定義物件在顯示(例如 admin 後台、印出物件)時的字串表達方式,提高可讀性:
1 | class Author(models.Model): |
在 admin 中或使用 print(author)
時,會顯示 Author: 張大明
而非 <Author object>
。
6.5 自定義查詢方法
你可以在模型中定義常用的查詢邏輯,提高重用性與可讀性。例如:
1 | class Product(models.Model): |
或者你也可以透過 Manager 自定義查詢集(更進階的用法):
1 | class ActiveProductManager(models.Manager): |
7. 整合 Django Admin 後台
Django 提供功能強大且即時可用的管理後台(Admin site),讓我們能快速檢視與操作資料庫中的資料。透過簡單的設定,就能將自訂模型整合進後台,並根據實際需求調整後台介面的顯示方式與操作便利性。
7.1 在 admin.py
中註冊模型(Model)
若要讓模型顯示在 Django Admin 後台中,需在對應的 app 資料夾內的 admin.py
檔案中註冊該模型。
1 | # blog/admin.py |
這樣一來,Article
模型就會出現在後台的操作介面中,預設提供新增、修改、刪除與列表功能。
7.2 自定義後台顯示樣式
為了讓資料管理更清晰與便利,我們可以透過自定義 ModelAdmin 類別的方式,客製化後台資料列表的顯示與搜尋行為。
7.2.1 list_display
:自訂列表顯示欄位
設定在模型列表頁中要顯示哪些欄位。
1 | class ArticleAdmin(admin.ModelAdmin): |
7.2.2 search_fields
:啟用關鍵字搜尋功能
讓管理員可以在後台透過關鍵字搜尋特定欄位內容。
1 | class ArticleAdmin(admin.ModelAdmin): |
支援外鍵欄位(使用 __
連結關聯欄位)。
7.2.3 list_filter
:側邊欄篩選器
可以根據特定欄位篩選資料,例如日期、狀態、分類等。
1 | class ArticleAdmin(admin.ModelAdmin): |
在後台列表頁左側會出現篩選選單,方便快速縮小資料範圍。
8. 進階技巧與實務應用
隨著 Django 專案越來越複雜,我們可以運用進階技巧讓程式更具可讀性、可維護性與彈性。以下介紹幾個常見的實務應用技巧,包括自定查詢邏輯、模型繼承、訊號機制、欄位優化與特殊欄位使用等。
8.1 使用 Managers
自定義查詢邏輯
在模型中可以透過自定義 Manager 來封裝複雜或常用的查詢邏輯。
範例:
1 | class PublishedArticleManager(models.Manager): |
使用方式:
1 | Article.published.all() # 只會回傳已發佈的文章 |
8.2 Model 繼承與抽象類別(Abstract Base Classes)
Django 支援模型繼承,可以建立一個「抽象基底模型」來共用欄位與邏輯,減少重複程式碼。
範例:
1 | class TimestampedModel(models.Model): |
這樣 Article
會自動繼承 created_at
和 updated_at
欄位,但不會建立 TimestampedModel
的資料表。
8.3 模型訊號(Model Signals)
Django 提供一組訊號機制(signals),允許我們在模型執行某些動作前後執行自訂邏輯。
常見訊號:
pre_save
:儲存前post_save
:儲存後pre_delete
/post_delete
範例:
1 | from django.db.models.signals import post_save |
這種方式可以用來做自動通知、紀錄日誌、建立關聯資料等用途。
8.4 善用 choices
設定列舉型欄位
當欄位只有固定選項時(例如文章狀態、性別、等級),可以使用 choices
增加資料一致性與後台清晰度。
範例:
1 | class Article(models.Model): |
在 admin 後台與表單中會自動顯示對應的中文標籤,增加可讀性。
8.5 使用進階欄位型別
Django 提供多種進階欄位型別,方便處理特殊需求資料:
8.5.1 UUIDField
:使用 UUID 作為主鍵或識別碼(更安全
1 | import uuid |
8.5.2 SlugField
:可讀性佳的網址段落(適合用於 SEO)
1 | class Article(models.Model): |
可以搭配 pre_save
或 slugify()
自動產生。
8.5.3 ImageField
:處理圖片上傳
1 | class Profile(models.Model): |
需要搭配 Pillow
套件安裝 pip install Pillow
。