Django Models 欄位類型完全指南 | Django 教學

2026/05/28 2026/05/22
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 儲存 TrueFalse,在 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 已正式移除。如果需要允許 TrueFalseNone 三種狀態,請改用 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

這兩個參數是 DateFieldDateTimeField 中最常用也最容易混淆的選項。

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_nowauto_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(兩位大寫字母 + 四位數字)',
            )
        ],
    )

欄位選項對照表

以下整理所有通用欄位選項的用途與預設值,方便快速查閱:

選項類型預設值說明
nullboolFalse允許資料庫儲存 NULL
blankboolFalse允許表單提交空值
defaultany-欄位預設值,可為值或可呼叫物件
uniqueboolFalse欄位值不可重複
db_indexboolFalse建立資料庫索引
primary_keyboolFalse設為主鍵(Primary Key),隱含 unique=True
verbose_namestr欄位名稱人類可讀的欄位名稱
help_textstr''表單中的輔助說明文字
validatorslist[]驗證器列表
choiceslist/enum-限定可選值
editableboolTrue是否可在表單中編輯
error_messagesdict-自訂錯誤訊息
db_columnstr欄位名稱自訂資料庫欄位名稱

常用欄位類型對照表

欄位類型對應 SQL 類型Python 類型必要參數適用場景
CharFieldVARCHAR(n)strmax_length標題、姓名
TextFieldTEXTstr-文章內容、描述
SlugFieldVARCHAR(50)str-URL 片段
EmailFieldVARCHAR(254)str-Email 地址
URLFieldVARCHAR(200)str-網址連結
IntegerFieldINTEGERint-數量、計數
FloatFieldDOUBLE PRECISIONfloat-座標、科學數據
DecimalFieldNUMERICDecimalmax_digits, decimal_places金額、精確計算
BooleanFieldBOOLEANbool-開關狀態
DateFieldDATEdate-生日、活動日
TimeFieldTIMEtime-營業時間
DateTimeFieldTIMESTAMPdatetime-建立/更新時間
FileFieldVARCHAR(100)FieldFile-文件上傳
ImageFieldVARCHAR(100)ImageFieldFile-圖片上傳

總結

在 Django Models 中選擇正確的欄位類型,是建立穩健資料架構的第一步。以下整理幾個核心要點:

  1. 字串欄位的選擇:短文字用 CharField(必須指定 max_length),長文字用 TextField。需要格式驗證時,優先使用 EmailFieldURLFieldSlugField 等內建欄位
  2. 金額計算用 DecimalFieldFloatField 有精度問題,涉及金錢或需要精確計算的場景務必使用 DecimalField
  3. 時間欄位善用 auto_now / auto_now_addauto_now_add 記錄建立時間,auto_now 記錄最後更新時間,兩者搭配使用是最常見的模式
  4. 選擇欄位推薦使用 TextChoices / IntegerChoices:比起傳統的 tuple 定義方式,列舉類型更具可讀性與型別安全性
  5. 理解 null 與 blank 的差異null 是資料庫層級,blank 是表單層級。字串欄位通常只需設定 blank=True

掌握這些欄位類型與選項後,你就能針對不同的業務需求,設計出結構清晰、驗證完善的 Django Model。下一篇我們將進入 Model 關聯(Relationships) 的世界,學習如何使用 ForeignKeyOneToOneFieldManyToManyField 建立表與表之間的關係。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。