MENU
\ お問い合わせはこちら! /

【Django】モデル・マイグレーション完全ガイド|フィールド設計からリレーションまで徹底解説

  • Djangoのモデルの書き方がわからない
  • フィールドの種類が多くて何を使えばいいか迷う
  • テーブル同士のリレーションをどう定義するか知りたい
  • マイグレーションの仕組みをちゃんと理解したい

この記事ではDjangoモデルの基本的な書き方から、よく使うフィールドの種類、テーブル間のリレーション設計、マイグレーションの仕組みまでをまとめて解説します。

モデルはDjangoの中心的な概念です。ここをしっかり理解しておくと、その後の開発がぐっとスムーズになります。

この記事を読む前に

  • Djangoのプロジェクト・アプリ構成を理解していること

まだの方はこちら →

Djangoモデルとは

Djangoのモデルは、データベースのテーブル構造をPythonクラスで表現したものです。

モデルを定義すると、DjangoがそのクラスをもとにSQLを自動生成してテーブルを作ってくれます。SQLを直接書く必要はありません。

  • モデルクラス
    Pythonクラス 1つ = データベーステーブル 1つ
  • フィールド
    クラスの属性 1つ = テーブルのカラム 1つ
  • マイグレーション
    モデルの変更内容をDBに反映する仕組み

基本的なモデルの定義

モデルは django.db.models.Model を継承したクラスとして models.py に書きます。

Python
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    published_at = models.DateTimeField(auto_now_add=True)
    is_published = models.BooleanField(default=False)

    def __str__(self):
        return self.title

__str__ は管理画面やシェルでオブジェクトを表示するときに使われる文字列を返します。必ず定義しておく習慣をつけましょう。

よく使うフィールド一覧

Djangoには用途ごとに多くのフィールドが用意されています。よく使うものをまとめました。

フィールド用途主なオプション
CharField短いテキスト(タイトル・名前など)max_length(必須)
TextField長いテキスト(本文・説明文など)
IntegerField整数
FloatField浮動小数点数
DecimalField固定小数点数(金額など)max_digits decimal_places(必須)
BooleanField真偽値default
DateField日付auto_now auto_now_add
DateTimeField日時auto_now auto_now_add
EmailFieldメールアドレス(形式バリデーション付き)max_length
URLFieldURL(形式バリデーション付き)
ImageField画像ファイルupload_to
FileField任意のファイルupload_to
JSONFieldJSONデータ

auto_now_add=True は作成時の日時を自動保存します。auto_now=True は更新のたびに現在日時に上書きします。どちらかを使えば手動でセットする必要はありません。

フィールドオプション

フィールドには共通して使えるオプションがあります。よく使う4つを覚えておけば十分です。

  • null=True
    DBのカラムにNULLを許可する。指定しない場合はNULLなし(デフォルト False
  • blank=True
    Djangoフォームの入力バリデーションで空欄を許可する(デフォルト False
  • default
    値が指定されなかったときのデフォルト値
  • verbose_name
    管理画面などに表示されるラベル名(日本語化に使う)
  • unique=True
    カラムに一意制約を付ける(重複値を禁止)

実際のコード例です。

Python
class Product(models.Model):
    name = models.CharField(
        max_length=100,
        verbose_name="商品名",
        unique=True,
    )
    description = models.TextField(
        blank=True,
        default="",
    )
    price = models.IntegerField(
        null=True,
        blank=True,
    )

nullblank は別物です。null はDB側の設定、blank はDjangoのバリデーション側の設定です。文字列系フィールド(CharField・TextField)は null=True を避けて blank=True, default="" の組み合わせが一般的なベストプラクティスです。

Metaクラス

モデルの内部に Meta クラスを書くと、テーブルの動作を細かく設定できます。

Python
class Article(models.Model):
    title = models.CharField(max_length=200)
    published_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-published_at"]
        verbose_name = "記事"
        verbose_name_plural = "記事一覧"
  • ordering
    デフォルトのソート順。"-published_at" はマイナスで降順(新しい順)
  • verbose_name
    管理画面での単数形の表示名
  • verbose_name_plural
    管理画面での複数形の表示名(設定しないと自動で末尾に “s” がつく)

リレーション

複数のテーブルを関連付けるリレーションは3種類あります。

ForeignKey(多対1)

「記事は1つのカテゴリに属する」「1つのカテゴリには複数の記事がある」といった多対1の関係に使います。最もよく使うリレーションです。

Python
class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=200)
    category = models.ForeignKey(
        Category,
        on_delete=models.CASCADE,
        related_name="articles",
    )
  • on_delete=models.CASCADE
    親レコード(Category)を削除したとき、紐づく子レコード(Article)もまとめて削除する
  • on_delete=models.SET_NULL
    親を削除したとき、子のFK列をNULLにする(null=True との併用が必要)
  • related_name
    逆方向アクセス時の名前。category.articles.all() のように使える

OneToOneField(1対1)

「ユーザー1人につきプロフィール1つ」のような1対1の関係に使います。Djangoの標準Userモデルを拡張するときの定番パターンです。

Python
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name="profile",
    )
    bio = models.TextField(blank=True)

カスタムユーザーモデルを使う場合は、User の代わりに settings.AUTH_USER_MODEL を参照するのがベストプラクティスです。詳しくはDjangoカスタムユーザーモデルを参照してください。

ManyToManyField(多対多)

「記事には複数のタグが付けられる。タグは複数の記事に付けられる」といった多対多の関係に使います。Djangoが自動的に中間テーブルを作成してくれます。

Python
class Tag(models.Model):
    name = models.CharField(max_length=50)

class Article(models.Model):
    title = models.CharField(max_length=200)
    tags = models.ManyToManyField(
        Tag,
        blank=True,
        related_name="articles",
    )

マイグレーション

モデルを定義・変更したら、マイグレーションでDBに反映します。2ステップで完了します。

Step 1: makemigrations(変更を検知してファイル生成)

モデルの変更内容をマイグレーションファイルとして生成します。実際のDBにはまだ反映されません。

Bash
python manage.py makemigrations

実行すると migrations/0001_initial.py のようなファイルが生成されます。このファイルはGitで管理してください。

Step 2: migrate(DBに反映)

生成されたマイグレーションファイルをDBに適用してテーブルを作成・変更します。

Bash
python manage.py migrate

マイグレーション状態の確認

どのマイグレーションが適用済みかを確認するには showmigrations を使います。[X] が適用済み、[ ] が未適用です。

Bash
python manage.py showmigrations

ロールバック(元に戻す)

特定のバージョンまで戻したい場合は、アプリ名とマイグレーション番号を指定します。

Bash
python manage.py migrate myapp 0001

本番環境のマイグレーションロールバックはデータが削除されるリスクがあります。開発環境でのみ使うか、事前にバックアップを取ってから実行してください。

まとめ

この記事ではDjangoモデルの基本から実践的な設計パターンまでを解説しました。

  • モデルはPythonクラスでDBテーブルを表現する
  • フィールドの種類とオプション(null・blank・default)を正しく使い分ける
  • リレーションは ForeignKey / OneToOneField / ManyToManyField の3種類
  • モデル変更後は makemigrations → migrate の2ステップでDBに反映する

モデルが定義できたら、次はデータの取得・更新・削除を行うQuerySet操作を学びましょう。

Djangoロードマップ全体はこちらから確認できます。

この記事が気に入ったら
フォローしてね!

シェア・記事の保存はこちら!

この記事を書いた人

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)