在 Django 模型中定義 CharFieldTextField 的選擇時,我們通常使用元組列表來實現。
然而,自 Django 3.0 起引入的 TextChoices,讓我們能夠編寫更簡潔且有意義的代碼


1. 模型選擇定義:傳統方式

我們常用的方式如下所示,為元組列表的形式。

# models.py
STATUS_CHOICES = [
    ('DF', 'Draft'),
    ('PB', 'Published'),
    ('AR', 'Archived'),
]

class Post(models.Model):
    status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='DF')

傳統方式的缺點: - 代碼意義難以理解(無法立即知道 'DF' 是什麼) - 雖然使用 get_FIELD_display(),但未以 Enum 風格結構化,維護上不便 - 需要在條件比較中進行硬編碼

if post.status == 'DF':
    ...

2. 以 TextChoices 方式進行改進


從源代碼來看,原理十分簡單,對原理感興趣的朋友,可以參考 Django 的源代碼。
這裡僅想說明使用方法。

# models.py 內部
from django.db import models

class PostStatus(models.TextChoices):
    DRAFT = 'DF', 'Draft'
    PUBLISHED = 'PB', 'Published'
    ARCHIVED = 'AR', 'Archived'

class Post(models.Model):
    status = models.CharField(max_length=2, choices=PostStatus.choices, default=PostStatus.DRAFT)

此方式的優點: - 可以用有意義的名稱如 PostStatus.DRAFT 進行條件處理 - 完美支持 get_status_display() - 像 Enum 一樣被視為對象,有利於 IDE 自動補全和靜態分析

if post.status == PostStatus.DRAFT:
    ...
  • 重用性: 若多個模型需要共享相同的選擇,可以將其定義在外部文件(choices.py)中

實際上 重用性 是使用 TextChoice 類別的最大優點之一。 若在 Django 的多個應用中共有的選擇,可以將其放置在 commons/choices.py 等文件中,從而在任何應用中調用這些選擇。


3. 結論


Django 的 TextChoices 是一個非常好的功能,可以幫助我們以更直觀且穩健的方式處理模型選擇。
脫離過去的元組列表方式,提升代碼質量到一個新高度吧!