Django Models 欄位類型完全指南 | Django 教學
在 Django 中,Model 是與資料庫互動的核心,而定義 Model 最關鍵的一步就是選擇正確的 欄位類型(Field Types)。每種欄位類型決定了資料的儲存格式、驗證規則與在 Django Admin 中的呈現方式。本篇將完整介紹所有常用欄位類型與通用選項,讓你在建立 Model 時不再猶豫。
字串欄位(String Fields)
字串欄位是最常使用的欄位類型,用來儲存各種文字資料。Django 提供了多種字串欄位,各自帶有不同的驗證規則。
CharField
CharField 用於儲存短文字,對應資料庫的 VARCHAR 類型。必須 指定 max_length 參數。
from django.db import models
class Product(models.Model):
# CharField 必須指定 max_length
name = models.CharField(max_length=200, verbose_name='產品名稱')
sku = models.CharField(max_length=50, unique=True, verbose_name='產品編號')
TextField
TextField 用於儲存大量文字,對應資料庫的 TEXT 類型,沒有長度限制。
class Article(models.Model):
title = models.CharField(max_length=200)
# TextField 適合存放長文內容
content = models.TextField(verbose_name='文章內容')
summary = models.TextField(blank=True, verbose_name='摘要')
SlugField
SlugField 是一種特殊的 CharField,只允許英文字母、數字、底線與連字符(hyphen),常用於 URL 網址片段(slug)。
class Post(models.Model):
title = models.CharField(max_length=200)
# SlugField 預設 max_length=50
slug = models.SlugField(max_length=200, unique=True)
# 產生的 URL 類似:/post/my-first-django-article/
EmailField
EmailField 內建電子郵件格式驗證(Email Validation),底層為 VARCHAR(254)。
class Contact(models.Model):
name = models.CharField(max_length=100)
# 自動驗證 Email 格式
email = models.EmailField(unique=True, verbose_name='電子郵件')
URLField
URLField 內建 URL 格式驗證,底層預設為 VARCHAR(200)。
class Company(models.Model):
name = models.CharField(max_length=200)
# 自動驗證 URL 格式
website = models.URLField(blank=True, verbose_name='公司網站')
數值欄位(Numeric Fields)
數值欄位用於儲存整數或小數,不同欄位類型對應不同的精度和範圍。
IntegerField
IntegerField 儲存整數,範圍為 -2,147,483,648 到 2,147,483,647。
class Product(models.Model):
name = models.CharField(max_length=200)
# 整數欄位,適合存放庫存數量
stock = models.IntegerField(default=0, verbose_name='庫存數量')
# PositiveIntegerField 只允許 0 及正整數
view_count = models.PositiveIntegerField(default=0, verbose_name='瀏覽次數')
FloatField
FloatField 儲存浮點數(Floating Point),對應資料庫的 DOUBLE PRECISION。由於浮點數有精度問題,不適合用於金額計算。
class Sensor(models.Model):
name = models.CharField(max_length=100)
# 浮點數適合用於科學數據、座標等
latitude = models.FloatField(verbose_name='緯度')
longitude = models.FloatField(verbose_name='經度')
DecimalField
DecimalField 儲存精確小數(Fixed-point Decimal),必須指定 max_digits(總位數)與 decimal_places(小數位數),適合金額計算。
class Order(models.Model):
product = models.CharField(max_length=200)
# max_digits=10 表示最多 10 位數字
# decimal_places=2 表示小數點後 2 位
# 最大值:99999999.99
price = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name='價格'
)
tax_rate = models.DecimalField(
max_digits=5,
decimal_places=4,
default=0.05,
verbose_name='稅率'
)
布林欄位(Boolean Fields)
BooleanField
BooleanField 儲存 True 或 False,在 Django Admin 中顯示為勾選框(Checkbox)。
class User(models.Model):
username = models.CharField(max_length=150)
# 預設值為 True
is_active = models.BooleanField(default=True, verbose_name='啟用狀態')
is_verified = models.BooleanField(default=False, verbose_name='已驗證')
NullBooleanField(已棄用)
NullBooleanField 在 Django 4.0 已正式移除。如果需要允許 True、False、None 三種狀態,請改用 BooleanField(null=True)。
class Survey(models.Model):
question = models.CharField(max_length=500)
# 舊寫法(已棄用):
# response = models.NullBooleanField()
# 新寫法:允許 True / False / None 三種狀態
response = models.BooleanField(null=True, blank=True, verbose_name='回覆')
日期時間欄位(Date and Time Fields)
日期時間欄位是幾乎每個 Model 都會用到的類型,用於記錄事件發生的時間點。
DateField
DateField 儲存日期(年-月-日),對應 Python 的 datetime.date 物件。
class Event(models.Model):
name = models.CharField(max_length=200)
# 儲存日期,格式為 YYYY-MM-DD
event_date = models.DateField(verbose_name='活動日期')
TimeField
TimeField 儲存時間(時:分:秒),對應 Python 的 datetime.time 物件。
class Schedule(models.Model):
name = models.CharField(max_length=200)
# 儲存時間,格式為 HH:MM:SS
start_time = models.TimeField(verbose_name='開始時間')
end_time = models.TimeField(verbose_name='結束時間')
DateTimeField
DateTimeField 同時儲存日期與時間,對應 Python 的 datetime.datetime 物件。
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
published_at = models.DateTimeField(
null=True,
blank=True,
verbose_name='發布時間'
)
auto_now vs auto_now_add
這兩個參數是 DateField 與 DateTimeField 中最常用也最容易混淆的選項。
class Article(models.Model):
title = models.CharField(max_length=200)
# auto_now_add=True:物件建立時自動設定,之後不再變動
# 適合用於「建立時間」
created_at = models.DateTimeField(auto_now_add=True)
# auto_now=True:每次 save() 時自動更新
# 適合用於「最後更新時間」
updated_at = models.DateTimeField(auto_now=True)
注意事項:
- 設定
auto_now或auto_now_add的欄位會自動變成editable=False,無法在 Admin 或表單中手動修改 - 如果需要手動設定時間,應使用
default=timezone.now取代auto_now_add QuerySet.update()不會 觸發auto_now,因為它不呼叫save()
檔案欄位(File Fields)
FileField
FileField 用於檔案上傳(File Upload),實際儲存的是檔案路徑字串,檔案本身存放在 MEDIA_ROOT 指定的目錄中。
class Document(models.Model):
title = models.CharField(max_length=200)
# upload_to 指定檔案儲存的子目錄
file = models.FileField(
upload_to='documents/%Y/%m/',
verbose_name='文件檔案'
)
# upload_to 支援日期格式化
# 上傳的檔案會存放在:MEDIA_ROOT/documents/2026/05/filename.pdf
使用 FileField 前,需要在 settings.py 中設定:
# settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
ImageField
ImageField 繼承自 FileField,額外驗證上傳的檔案是否為有效圖片格式。需要安裝 Pillow 套件。
# 先安裝 Pillow:pip install Pillow
class UserProfile(models.Model):
user = models.OneToOneField('auth.User', on_delete=models.CASCADE)
# ImageField 會驗證檔案是否為有效圖片
avatar = models.ImageField(
upload_to='avatars/',
blank=True,
null=True,
verbose_name='大頭照'
)
# 可以搭配 width_field 和 height_field 自動記錄圖片尺寸
cover_image = models.ImageField(
upload_to='covers/',
width_field='cover_width',
height_field='cover_height',
blank=True,
)
cover_width = models.PositiveIntegerField(null=True, blank=True)
cover_height = models.PositiveIntegerField(null=True, blank=True)
選擇欄位(Choice Fields)
當欄位的值限定在一組固定選項中時,可以使用 choices 參數。
基本 choices 用法
class Order(models.Model):
# 使用 tuple 定義選項:(儲存值, 顯示文字)
STATUS_CHOICES = [
('pending', '待處理'),
('processing', '處理中'),
('shipped', '已出貨'),
('delivered', '已送達'),
('cancelled', '已取消'),
]
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='pending',
verbose_name='訂單狀態',
)
TextChoices 與 IntegerChoices(Django 3.0+)
Django 3.0 引入了 列舉類型(Enumeration Types),提供更優雅且型別安全的方式來定義選項。
class Article(models.Model):
# TextChoices:值為字串
class Status(models.TextChoices):
DRAFT = 'draft', '草稿'
REVIEW = 'review', '審核中'
PUBLISHED = 'published', '已發布'
ARCHIVED = 'archived', '已封存'
status = models.CharField(
max_length=10,
choices=Status.choices, # 自動產生 choices tuple
default=Status.DRAFT, # 使用列舉成員作為預設值
verbose_name='狀態',
)
# IntegerChoices:值為整數
class Priority(models.IntegerChoices):
LOW = 1, '低'
MEDIUM = 2, '中'
HIGH = 3, '高'
URGENT = 4, '緊急'
priority = models.IntegerField(
choices=Priority.choices,
default=Priority.MEDIUM,
verbose_name='優先度',
)
# 使用方式
article = Article(status=Article.Status.DRAFT, priority=Article.Priority.HIGH)
# 取得顯示文字
article.get_status_display() # '草稿'
article.get_priority_display() # '高'
# 比較時可以使用列舉成員
if article.status == Article.Status.PUBLISHED:
print('文章已發布')
通用欄位選項(Common Field Options)
以下選項適用於所有欄位類型,是定義 Model 時經常需要設定的參數。
null 與 blank
class Example(models.Model):
# null=True:資料庫層級,允許儲存 NULL
# blank=True:表單層級,允許提交空值
# 字串欄位建議只用 blank=True(空值以空字串 '' 儲存)
nickname = models.CharField(max_length=100, blank=True)
# 非字串欄位需要同時設定 null=True 和 blank=True
birthday = models.DateField(null=True, blank=True)
default
class Config(models.Model):
# 靜態預設值
retry_count = models.IntegerField(default=3)
is_enabled = models.BooleanField(default=True)
# 可呼叫物件作為預設值(每次建立實例時呼叫)
metadata = models.JSONField(default=dict) # 正確:傳入 dict 類別
# metadata = models.JSONField(default={}) # 錯誤:所有實例共用同一個 dict
unique 與 db_index
class User(models.Model):
# unique=True:欄位值不可重複,自動建立資料庫索引
email = models.EmailField(unique=True)
# db_index=True:建立資料庫索引,加速查詢
username = models.CharField(max_length=150, db_index=True)
verbose_name 與 help_text
class Product(models.Model):
# verbose_name:欄位的人類可讀名稱,用於 Admin 與表單標籤
name = models.CharField(max_length=200, verbose_name='產品名稱')
# help_text:欄位的輔助說明文字,顯示在 Admin 表單欄位下方
price = models.DecimalField(
max_digits=10,
decimal_places=2,
help_text='請輸入含稅價格,單位為新台幣',
)
validators
from django.core.validators import (
MinValueValidator,
MaxValueValidator,
RegexValidator,
)
class Product(models.Model):
name = models.CharField(max_length=200)
# 使用內建驗證器限制數值範圍
rating = models.IntegerField(
validators=[MinValueValidator(1), MaxValueValidator(5)],
verbose_name='評分',
help_text='評分範圍為 1 到 5',
)
# 使用正則表達式驗證器
product_code = models.CharField(
max_length=20,
validators=[
RegexValidator(
regex=r'^[A-Z]{2}-\d{4}$',
message='產品編號格式須為 XX-0000(兩位大寫字母 + 四位數字)',
)
],
)
欄位選項對照表
以下整理所有通用欄位選項的用途與預設值,方便快速查閱:
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
null | bool | False | 允許資料庫儲存 NULL |
blank | bool | False | 允許表單提交空值 |
default | any | - | 欄位預設值,可為值或可呼叫物件 |
unique | bool | False | 欄位值不可重複 |
db_index | bool | False | 建立資料庫索引 |
primary_key | bool | False | 設為主鍵(Primary Key),隱含 unique=True |
verbose_name | str | 欄位名稱 | 人類可讀的欄位名稱 |
help_text | str | '' | 表單中的輔助說明文字 |
validators | list | [] | 驗證器列表 |
choices | list/enum | - | 限定可選值 |
editable | bool | True | 是否可在表單中編輯 |
error_messages | dict | - | 自訂錯誤訊息 |
db_column | str | 欄位名稱 | 自訂資料庫欄位名稱 |
常用欄位類型對照表
| 欄位類型 | 對應 SQL 類型 | Python 類型 | 必要參數 | 適用場景 |
|---|---|---|---|---|
CharField | VARCHAR(n) | str | max_length | 標題、姓名 |
TextField | TEXT | str | - | 文章內容、描述 |
SlugField | VARCHAR(50) | str | - | URL 片段 |
EmailField | VARCHAR(254) | str | - | Email 地址 |
URLField | VARCHAR(200) | str | - | 網址連結 |
IntegerField | INTEGER | int | - | 數量、計數 |
FloatField | DOUBLE PRECISION | float | - | 座標、科學數據 |
DecimalField | NUMERIC | Decimal | max_digits, decimal_places | 金額、精確計算 |
BooleanField | BOOLEAN | bool | - | 開關狀態 |
DateField | DATE | date | - | 生日、活動日 |
TimeField | TIME | time | - | 營業時間 |
DateTimeField | TIMESTAMP | datetime | - | 建立/更新時間 |
FileField | VARCHAR(100) | FieldFile | - | 文件上傳 |
ImageField | VARCHAR(100) | ImageFieldFile | - | 圖片上傳 |
總結
在 Django Models 中選擇正確的欄位類型,是建立穩健資料架構的第一步。以下整理幾個核心要點:
- 字串欄位的選擇:短文字用
CharField(必須指定max_length),長文字用TextField。需要格式驗證時,優先使用EmailField、URLField、SlugField等內建欄位 - 金額計算用 DecimalField:
FloatField有精度問題,涉及金錢或需要精確計算的場景務必使用DecimalField - 時間欄位善用 auto_now / auto_now_add:
auto_now_add記錄建立時間,auto_now記錄最後更新時間,兩者搭配使用是最常見的模式 - 選擇欄位推薦使用 TextChoices / IntegerChoices:比起傳統的 tuple 定義方式,列舉類型更具可讀性與型別安全性
- 理解 null 與 blank 的差異:
null是資料庫層級,blank是表單層級。字串欄位通常只需設定blank=True
掌握這些欄位類型與選項後,你就能針對不同的業務需求,設計出結構清晰、驗證完善的 Django Model。下一篇我們將進入 Model 關聯(Relationships) 的世界,學習如何使用 ForeignKey、OneToOneField 與 ManyToManyField 建立表與表之間的關係。