基本

Djangoモデルの定義方法|データベース設計の基本

Django モデル データベース

Djangoモデルの定義方法
データベース設計の基本

Djangoのモデルは、Pythonのクラスでデータベースのテーブル構造を定義する仕組みです。
この記事では、モデルの基本的なフィールド定義からリレーション、マイグレーションまでを解説します。

こんな人向けの記事です

  • Djangoでデータベースを使いたい
  • モデルの各フィールドの使い方を知りたい
  • テーブル同士のリレーションを定義したい

Step 1基本のモデル定義

models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title
要素役割
models.ModelDjangoモデルの基底クラス(必ず継承する)
各フィールドデータベースのカラムに対応
__str__管理画面やshellでの表示名

Step 2よく使うフィールド一覧

フィールド用途SQLカラム
CharField(max_length=N)短い文字列(タイトル等)VARCHAR
TextField()長い文字列(本文等)TEXT
IntegerField()整数INTEGER
FloatField()小数FLOAT
DecimalField(max_digits, decimal_places)高精度小数(金額等)DECIMAL
BooleanField()真偽値BOOLEAN
DateField()日付DATE
DateTimeField()日時DATETIME
EmailField()メールアドレスVARCHAR(バリデーション付き)
URLField()URLVARCHAR(バリデーション付き)
SlugField()URLスラッグVARCHAR
ImageField(upload_to=)画像ファイルVARCHAR(パス保存)
FileField(upload_to=)ファイルVARCHAR(パス保存)

Step 3フィールドオプション

オプション意味デフォルト
null=TrueDBにNULLを許可False
blank=Trueフォームで空欄を許可False
default=値デフォルト値なし
unique=True重複を禁止False
db_index=Trueインデックスを作成False
verbose_name管理画面での表示名フィールド名
choices選択肢を制限なし
models.py
class Product(models.Model):
    STATUS_CHOICES = [
        ('draft', '下書き'),
        ('published', '公開'),
        ('archived', 'アーカイブ'),
    ]

    name = models.CharField('商品名', max_length=200)
    price = models.DecimalField('価格', max_digits=10, decimal_places=0)
    description = models.TextField('説明', blank=True)
    status = models.CharField('状態', max_length=20, choices=STATUS_CHOICES, default='draft')
    created_at = models.DateTimeField('作成日', auto_now_add=True)
null と blank の違い
null=True → データベースレベル(NULLを許可)
blank=True → バリデーションレベル(空欄を許可)
文字列フィールドは blank=True のみ推奨(空文字で保存)。
日付や数値は null=True, blank=True の両方を指定。

Step 4リレーション(ForeignKey / ManyToMany)

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

class Article(models.Model):
    title = models.CharField(max_length=200)

    # 多対1(記事は1つのカテゴリに属する)
    category = models.ForeignKey(
        Category,
        on_delete=models.CASCADE,  # カテゴリ削除時に記事も削除
        related_name='articles',   # 逆参照名
    )

    # 多対多(記事は複数のタグを持てる)
    tags = models.ManyToManyField('Tag', blank=True)

class Tag(models.Model):
    name = models.CharField(max_length=50)
on_delete動作
CASCADE親を削除すると子も削除
PROTECT子がある場合、親の削除をエラーにする
SET_NULL親削除時にNULLをセット(null=True必要)
SET_DEFAULT親削除時にdefault値をセット

Step 5マイグレーション

ターミナル
# マイグレーションファイルを作成
python manage.py makemigrations

# マイグレーションを実行(テーブルを作成/変更)
python manage.py migrate

# マイグレーション状態を確認
python manage.py showmigrations

# SQLを確認(実行はしない)
python manage.py sqlmigrate app_name 0001

Step 6Metaクラス

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

    class Meta:
        ordering = ['-created_at']       # デフォルトの並び順(新しい順)
        verbose_name = '記事'            # 管理画面での単数名
        verbose_name_plural = '記事一覧'  # 管理画面での複数名
        db_table = 'articles'            # テーブル名を指定
        indexes = [
            models.Index(fields=['created_at']),
        ]

まとめ

  • models.Model を継承してモデルクラスを定義
  • CharField, TextField, IntegerField 等でフィールドを定義
  • ForeignKey で多対1、ManyToManyField で多対多リレーション
  • makemigrationsmigrate でDBに反映
  • Meta クラスで並び順、テーブル名、インデックスを設定