Djangoで、モデルを設計しているとき、選択肢のどれかを値にもつフィールドを実装することがあると思います。
その時の実装方法の使い分けや注意点をまとめてみました。
選択肢フィールドの実装方法3通り
以下の3つが主な実装パターンです。
- 外部キーを使う(
ForeignKey
やManyToManyField
など) - タプルリストを使う
-
models.TextChoices
を使う
使い分けの目安は以下のとおりです:
- 選択肢を動的に追加・変更したい → 1. 外部キー
- 選択肢が一度きりの使い捨てで良い → 2. タプルリスト
-
選択肢が固定で、再利用・定数アクセスしたい → 3.
models.TextChoices
それぞれ詳しく解説します。
1. 外部キーを使う
最も汎用性が高い方法です。
たとえば、Articleモデルがauthorのフィールドを持つ場合、Userモデル等を ForeignKey
で紐づけると、後から選択肢を管理画面などで追加・変更しやすくなります。
また、Articleモデルにタグをつけたい場合などは、TagモデルをManyToManyField
で紐付けると便利です。
注意点:
on_delete=models.CASCADE
を安易に使わず、models.PROTECT
や models.SET_NULL
など、アプリの仕様に応じて適切に設定しましょう。
例えば、ある執筆者が選択肢から不要になっても、models.CASCADEにしているとそれを削除したらその執筆者が書いた記事まで削除されてしまいます。
2. タプルリストを使う
簡単に実装したいときに使える方法です。
ちょっとした用途で使い捨ての選択肢が必要な場合に適しています。
MVP(Minimum Viable Product)を作るときにも適しています。
例:性別の選択肢(追加・変更の予定がない場合)
GENDER_CHOICES = [
("male", "男性"),
("female", "女性"),
("other", "その他/不明"),
]
class User(AbstractUser):
gender = models.CharField(max_length=10, choices=GENDER_CHOICES)
非常に簡単ですが、保守性や再利用性を考えると、以下の TextChoices
を使った方が良い場面が多いです。
3. models.TextChoices
を使う
選択肢が固定で、複数のモデルで使い回したい場合は、models.TextChoices
が便利です。
たとえば、User
モデルと Customer
モデルの両方で性別フィールドを持たせたい場合、以下のように共通クラスを定義できます。
class Gender(models.TextChoices):
MALE = "male", "男性"
FEMALE = "female", "女性"
OTHER = "other", "その他/不明"
class User(AbstractUser):
gender = models.CharField(
max_length=10,
choices=Gender.choices,
default=Gender.OTHER,
)
class Customer(models.Model):
gender = models.CharField(
max_length=10,
choices=Gender.choices,
default=Gender.OTHER,
)
TextChoices の構文
サンプルコードを見てもらえば、なんとなく分かると思いますが、それぞれの選択肢を、
"変数名" = "保存値", "表示ラベル"
のように書きます。
- 保存値:DBに保存される値(英語など短い文字列)
- 表示ラベル:管理画面やフォームなどに表示される日本語ラベルなど
です。
利点:定数アクセスとテンプレート表示が簡単
TextChoices
を使うと、定数アクセスができて、以下のように条件文で活用できたり、
if user.gender == Gender.MALE:
...
初期期をdefault=Gender.OTHERのように簡単に設定できます
また、テンプレートでは .get_FOO_display
を使って簡単に表示できます(FOO
はフィールド名)。自分で表示するロジックを書く必要がありません。
{{ user.get_gender_display }}
まとめ
方法 | 向いている用途 | 再利用性 | 保守性 |
---|---|---|---|
外部キー | 動的に管理したい選択肢 | 高い | 高い |
タプルリスト | 単発・簡易用途 | 低い | 低い |
TextChoices |
再利用・定数アクセスしたい | 高い | 高い |
選択肢の性質や再利用性を考慮して、最適な方法を選びましょう。