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.Model | Djangoモデルの基底クラス(必ず継承する) |
| 各フィールド | データベースのカラムに対応 |
__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() | URL | VARCHAR(バリデーション付き) |
SlugField() | URLスラッグ | VARCHAR |
ImageField(upload_to=) | 画像ファイル | VARCHAR(パス保存) |
FileField(upload_to=) | ファイル | VARCHAR(パス保存) |
Step 3フィールドオプション
| オプション | 意味 | デフォルト |
|---|---|---|
null=True | DBに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で多対多リレーションmakemigrations→migrateでDBに反映Metaクラスで並び順、テーブル名、インデックスを設定