
目次
- 1 user@sinyblog:~/article ❯ 01_concepts.mdレコード削除 vs テーブル削除 — 何が違うのか?
- 2 user@sinyblog:~/article ❯ 02_sample_models.mdサンプルモデル(家計簿アプリ)
- 3 user@sinyblog:~/article ❯ 03_delete_records.md【パターン1】レコードを削除する — delete() の全パターン
- 4 user@sinyblog:~/article ❯ 04_drop_table.md【パターン2】テーブル(モデル)ごと削除する
- 5 user@sinyblog:~/article ❯ 05_flush_reset.md【パターン3】全データをリセットする — flush と DB 再生成
- 6 user@sinyblog:~/article ❯ 06_troubleshoot.mdよくあるトラブルと対処
- 7 user@sinyblog:~/article ❯ 99_summary.mdまとめ — 用途別チートシート
Django · Database Operations · 2026 Edition
Django で「データを削除したい」と一口に言っても、実は レコード(データ行)を消すのと テーブル(モデル)そのものを消すのは全く別の操作です。本記事では、レコード削除(delete())、テーブル削除(drop table + migrate)、全データのリセット(flush)の使い分けを、実際の家計簿アプリのモデルを例に、手順とハマりどころを含めて完全解説します。所要時間 15 分。
user@sinyblog:~/article ❯ 01_concepts.mdレコード削除 vs テーブル削除 — 何が違うのか?
まず最初に、Django で「削除」と言ったときに混同されがちな 3 種類の操作を整理しておきます。
| 操作 | 消えるもの | 使うコマンド | 使う場面 |
|---|---|---|---|
| レコード削除 | テーブル内のデータ行(テーブル定義は残る) | Model.objects.delete() (ORM) |
古いデータを消す、ユーザー操作で削除、テスト用データのクリーンアップ |
| テーブル削除 | テーブル定義そのもの(中身もろとも) | drop table + migrate 操作 |
不要になったモデルの撤去、設計変更で古いテーブルを除去 |
| 全データリセット | 全テーブルのデータのみ(定義は残る) | python manage.py flush |
テスト前の DB クリーンアップ、開発環境のリセット |
「特定のレコード(行)を消したい」→ パターン1(レコード削除)。「もう使わないモデル(テーブル)自体を消したい」→ パターン2(テーブル削除)。「テスト前にデータだけ全部消したい」→ パターン3(flush)。本記事ではこの 3 パターンを順に解説します。
user@sinyblog:~/article ❯ 02_sample_models.mdサンプルモデル(家計簿アプリ)
本記事の例では、以下 3 つのモデルを持つ家計簿アプリ(kakeibo)を題材にします。データベースは SQLite3 です。
from django.db import models
from datetime import datetime
class Category(models.Model):
class Meta:
verbose_name = "カテゴリ"
verbose_name_plural = "カテゴリ"
category_name = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.category_name
class Kakeibo(models.Model):
class Meta:
verbose_name = "家計簿"
verbose_name_plural = "家計簿"
date = models.DateField("日付", default=datetime.now)
category = models.ForeignKey(Category, on_delete=models.PROTECT, verbose_name="カテゴリ")
money = models.IntegerField("金額", help_text="単位は日本円")
quantity = models.IntegerField(verbose_name="数量", default=0)
memo = models.CharField(verbose_name="メモ", max_length=500)
def __str__(self):
return self.memo
class User(models.Model):
class Meta:
verbose_name = "ユーザテーブル"
verbose_name_plural = "ユーザテーブル"
user_name = models.CharField(max_length=255, unique=True)
address = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.user_name
user@sinyblog:~/article ❯ 03_delete_records.md【パターン1】レコードを削除する — delete() の全パターン
テーブル定義はそのままに、データ行(レコード)だけを消したい場合は、Django の ORM が提供する delete() メソッドを使います。これが最もよく使う「削除」操作です。
① 単一レコードを削除
主キー(pk) で対象を絞り込んで削除します。
from kakeibo.models import Kakeibo
# pk=5 のレコードを取得して削除
record = Kakeibo.objects.get(pk=5)
record.delete()
# (1, {'kakeibo.Kakeibo': 1}) ← 削除件数と内訳が返る
get() は対象が存在しないと DoesNotExist 例外を投げます。本番コードでは filter().first() + None チェック、または try/except で囲むのが安全です。
② 条件で複数レコードを一括削除
filter() で絞り込んだ QuerySet にそのまま delete() を呼ぶと、SQL の DELETE 文 1 発で一括削除 されます。Python のループで 1 件ずつ消すより圧倒的に高速です。
# 2024 年以前の家計簿レコードを全削除
from datetime import date
Kakeibo.objects.filter(date__lt=date(2024, 1, 1)).delete()
# 金額が 100 円未満のレコードを削除
Kakeibo.objects.filter(money__lt=100).delete()
# 特定カテゴリのレコードを削除
Kakeibo.objects.filter(category__category_name="食費").delete()
③ 全レコードを削除
テーブル内のすべてのレコードを削除する場合は all().delete() を使います。テーブル定義は残る ので、再度データを INSERT できる状態が保たれます。
# Kakeibo テーブルの全レコードを削除
Kakeibo.objects.all().delete()
削除前に .count() で件数を確認するクセをつけると事故を防げます。filter の条件ミスで全削除…という事故は意外と多いです。
# まず削除対象の件数を確認
qs = Kakeibo.objects.filter(date__lt=date(2024, 1, 1))
print(f"削除対象: {qs.count()} 件")
# 想定通りの件数なら実行
qs.delete()
④ 関連レコード(ForeignKey)の連動削除
ForeignKey を持つモデルでは、親レコードを削除したときに子レコードがどうなるかを on_delete オプションで制御します。サンプルの Kakeibo モデルでは on_delete=models.PROTECT を指定しているので、参照されている Category は削除できません。
| on_delete オプション | 挙動 |
|---|---|
CASCADE |
親を削除すると、参照している子レコードも自動削除 |
PROTECT |
子レコードが残っている場合、親の削除を拒否(ProtectedError) |
SET_NULL |
親削除時、子の外部キーを NULL に置換(null=True 必須) |
SET_DEFAULT |
親削除時、子の外部キーをデフォルト値に置換 |
DO_NOTHING |
何もしない(DB 側の制約に委ねる、上級者向け) |
from kakeibo.models import Category
# Category("食費") が Kakeibo に参照されていると…
Category.objects.filter(category_name="食費").delete()
# → django.db.models.deletion.ProtectedError 発生!
# 先に子レコード(Kakeibo)を削除してから親を消す必要がある
Kakeibo.objects.filter(category__category_name="食費").delete()
Category.objects.filter(category_name="食費").delete() # OK
user@sinyblog:~/article ❯ 04_drop_table.md【パターン2】テーブル(モデル)ごと削除する
こちらは少し重い操作で、「もう使わないモデルを撤去したい」場合の手順です。サンプルでは User テーブルが不要になったケースで進めます。
本番 DB で実施する場合は、必ずスナップショット or dumpdata でバックアップを取ってから始めてください。途中失敗するとリカバリーが面倒です。
Step 1. 現状の整合確認
まず makemigrations で「変更なし」状態であることを確認します。
python manage.py makemigrations
# No changes detected ← この状態にしてから次へ進む
python manage.py showmigrations
# kakeibo
# [X] 0001_initial
# [X] 0002_auto_20181204_1157
# [X] 0003_kakeibo_quantity
# [X] 0004_user
Step 2. Migrations 履歴を fake で巻き戻す
--fake オプション付きの migrate で、実 DB を変更せずに履歴だけ巻き戻します。
python manage.py migrate --fake kakeibo zero
# Operations to perform:
# Unapply all migrations: kakeibo
# Running migrations:
# Unapplying kakeibo.0004_user... FAKED
# Unapplying kakeibo.0003_kakeibo_quantity... FAKED
# Unapplying kakeibo.0002_auto_20181204_1157... FAKED
# Unapplying kakeibo.0001_initial... FAKED
python manage.py showmigrations
# kakeibo
# [ ] 0001_initial
# [ ] 0002_auto_20181204_1157
# [ ] 0003_kakeibo_quantity
# [ ] 0004_user
# ↑ [X] が [ ] に変わっていれば OK
Step 3. Migrations ファイルを物理削除
kakeibo/migrations/ 配下の __init__.py 以外 の xxxx.py ファイル(0001_initial.py など)を全て削除します。
python manage.py showmigrations
# kakeibo
# (no migrations) ← この状態になれば OK
Step 4. 実 DB から該当テーブルを DROP
SQLite3 の場合は dbshell から drop table で物理削除します。他の DB(PostgreSQL / MySQL)でも同等のコマンドで OK。
python manage.py dbshell
sqlite> .tables
auth_group django_content_type
auth_group_permissions django_migrations
auth_permission django_session
auth_user kakeibo_category
auth_user_groups kakeibo_kakeibo
auth_user_user_permissions kakeibo_user ← これを消す
django_admin_log
sqlite> drop table kakeibo_user;
sqlite> .tables
# kakeibo_user が消えていることを確認
Step 5. models.py / admin.py から該当モデルの定義を削除
models.py から class User(models.Model): 全体を削除。admin.py や views.py から User を参照している箇所も合わせて削除します。
Step 6. Migrations を再生成して整合をとる
# User を除いた状態で初期マイグレーションを再生成
python manage.py makemigrations
# Migrations for 'kakeibo':
# kakeibo\migrations\0001_initial.py
# - Create model Category
# - Create model Kakeibo
# 既存テーブル(Category, Kakeibo)は実 DB に存在するので fake で履歴だけ進める
python manage.py migrate --fake-initial
# Applying kakeibo.0001_initial... FAKED
# 最終確認
python manage.py showmigrations
# kakeibo
# [X] 0001_initial
python manage.py makemigrations kakeibo
# No changes detected in app 'kakeibo'
python manage.py runserver
# 起動して画面が問題なく動けば完了
user@sinyblog:~/article ❯ 05_flush_reset.md【パターン3】全データをリセットする — flush と DB 再生成
「テスト前に全データをまっさらにしたい」「開発環境のシードデータを入れ直したい」場合は、テーブル定義を残したままデータだけ消す flush コマンドが便利です。
flush — 全テーブルのデータを削除(構造は残る)
python manage.py flush
# You have requested a flush of the database.
# This will IRREVERSIBLY DESTROY all data currently in the database
# Are you sure you want to do this?
# Type 'yes' to continue, or 'no' to cancel: yes
テーブル構造はそのまま残るため、再度 INSERT できる状態が保たれます。スーパーユーザーも消えるので、必要なら再作成します。
DB ファイル削除 + 再生成(SQLite3 限定の最終手段)
SQLite3 の場合、開発環境なら DB ファイルを物理削除してから再 migrate するのが最速です。
# DB ファイルを削除
rm db.sqlite3 # macOS / Linux
del db.sqlite3 # Windows
# 全テーブルを再生成
python manage.py migrate
# スーパーユーザー再作成
python manage.py createsuperuser
DB ファイル削除は 開発環境専用 の操作です。本番では flush でも復元不可能。必ず事前バックアップ + 確認手順を徹底してください。
user@sinyblog:~/article ❯ 06_troubleshoot.mdよくあるトラブルと対処
| 症状 | 原因 | 対処 |
|---|---|---|
ProtectedError で削除できない |
ForeignKey の on_delete=PROTECT で参照中 |
先に子レコードを削除する。または on_delete=CASCADE に変更 |
django.db.utils.OperationalError: no such table |
migrate されていない or テーブルが手動 DROP された | python manage.py migrate を実行 |
テーブル削除後に showmigrations が不整合 |
履歴と実 DB がズレている | migrate --fake で履歴を実 DB に合わせる |
delete() したのに件数が 0 のまま |
QuerySet を変数に入れる前に .delete() を呼んだ等の論理ミス |
.count() で対象件数を確認してから実行 |
大量データの delete() が遅い |
シグナル処理 + ForeignKey の連動チェック | _raw_delete()(Django内部API)、または SQL 直接実行を検討 |
user@sinyblog:~/article ❯ 99_summary.mdまとめ — 用途別チートシート
用途別の選び方を一覧で振り返ります。
| やりたいこと | 使うコマンド |
|---|---|
| 1 件だけ消したい | Model.objects.get(pk=N).delete() |
| 条件で複数消したい | Model.objects.filter(...).delete() |
| あるテーブルの全レコード消したい | Model.objects.all().delete() |
| 全テーブルのデータだけ消したい | python manage.py flush |
| 不要モデル(テーブル)ごと撤去したい | パターン2の Step 1〜6 を順に実施 |
| 開発環境を完全初期化したい | DB ファイル削除 + python manage.py migrate |
「削除」と一括りにしても、消したいレベル(レコード / テーブル / DB全体) によって使うコマンドが全く違います。本記事のパターンを使い分けて、安全かつ意図通りの削除を実現してください。
delete())の章と全データリセット(flush)の章を追加して、3 種類の削除パターンを完全カバーする総合ガイドに再構成しました。元のテーブル削除手順は維持しつつ、検索者の本命ニーズである「レコード削除」を最初に配置しています。運営者(現役 IT エンジニア・15 年以上の業界経験)。

