0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Django]選択肢から選ばせるフィールドの実装方法

Last updated at Posted at 2025-05-05

Djangoで、モデルを設計しているとき、選択肢のどれかを値にもつフィールドを実装することがあると思います。
その時の実装方法の使い分けや注意点をまとめてみました。

選択肢フィールドの実装方法3通り

以下の3つが主な実装パターンです。

  1. 外部キーを使う(ForeignKeyManyToManyField など)
  2. タプルリストを使う
  3. models.TextChoices を使う

使い分けの目安は以下のとおりです:

  • 選択肢を動的に追加・変更したい → 1. 外部キー
  • 選択肢が一度きりの使い捨てで良い → 2. タプルリスト
  • 選択肢が固定で、再利用・定数アクセスしたい → 3. models.TextChoices

それぞれ詳しく解説します。

1. 外部キーを使う

最も汎用性が高い方法です。

たとえば、Articleモデルがauthorのフィールドを持つ場合、Userモデル等を ForeignKey で紐づけると、後から選択肢を管理画面などで追加・変更しやすくなります。

また、Articleモデルにタグをつけたい場合などは、TagモデルをManyToManyField で紐付けると便利です。

注意点
on_delete=models.CASCADE を安易に使わず、models.PROTECTmodels.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 再利用・定数アクセスしたい 高い 高い

選択肢の性質や再利用性を考慮して、最適な方法を選びましょう。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?