タイトル: エラー一覧
SEOタイトル: Django のよくあるエラー一覧と対処法 — OperationalError から CSRF まで
| この記事の要点 |
|
1. OperationalError
DB 関連の最頻出エラー。 接続情報・ネットワーク・テーブル不在など多岐:
django.db.utils.OperationalError: could not connect to server: Connection refused
django.db.utils.OperationalError: (1045, "Access denied for user 'root'@'localhost'")
django.db.utils.OperationalError: no such table: blog_article
django.db.utils.OperationalError: (1146, "Table 'mydb.blog_article' doesn't exist")
| 原因 | 対処 |
|---|---|
| DB サーバ停止 | systemctl status postgresql / MySQL サービス起動 |
| 接続情報誤り | settings.py の HOST/PORT/USER/PASSWORD 再確認 |
| テーブル不在 | python manage.py migrate 実行 |
| 権限不足 | DB ユーザに GRANT ALL ON dbname.* TO user@host |
| ネットワーク | ファイアウォール、 セキュリティグループ確認 |
2. IntegrityError
制約違反(UNIQUE / NOT NULL / FK):
# UNIQUE 制約違反
django.db.utils.IntegrityError: UNIQUE constraint failed: blog_article.slug
# 対処: 重複チェック後に作成
if not Article.objects.filter(slug=slug).exists():
Article.objects.create(slug=slug, ...)
# または get_or_create
article, created = Article.objects.get_or_create(
slug=slug,
defaults={'title': title, 'body': body},
)
# NOT NULL 制約違反
django.db.utils.IntegrityError: NOT NULL constraint failed: blog_article.author_id
# 対処: 必須フィールドを必ず指定 or モデルに null=True / default 付与
3. DoesNotExist / MultipleObjectsReturned
# DoesNotExist: get() で見つからない
art = Article.objects.get(pk=999)
# blog.models.Article.DoesNotExist: Article matching query does not exist.
# 対処パターン
# 1. filter().first()
art = Article.objects.filter(pk=999).first() # 無ければ None
# 2. get_object_or_404 (ビューで便利)
from django.shortcuts import get_object_or_404
art = get_object_or_404(Article, pk=999)
# 3. try/except
try:
art = Article.objects.get(pk=999)
except Article.DoesNotExist:
art = None
# MultipleObjectsReturned: get() で複数該当
Article.objects.get(category__slug='tech')
# MultipleObjectsReturned: get() returned more than one Article
# 対処: filter() を使う、 または unique 制約見直し
arts = Article.objects.filter(category__slug='tech')
4. TemplateDoesNotExist
django.template.exceptions.TemplateDoesNotExist: blog/article_list.html
# テンプレート検索順序:
# 1. TEMPLATES[0]['DIRS'] のフォルダ
# 2. 各 INSTALLED_APPS の templates/ サブフォルダ (APP_DIRS=True 時)
対処:
- ファイルパスを確認 —
blog/templates/blog/article_list.html構成が定石(アプリ名サブフォルダ) settings.pyのTEMPLATES[0]['APP_DIRS']がTrueか確認- プロジェクト共通テンプレートは
BASE_DIR / 'templates'をDIRSに追加 - アプリが
INSTALLED_APPSに登録されているか確認
5. NoReverseMatch
django.urls.exceptions.NoReverseMatch:
Reverse for 'article_detail' with arguments '(1,)' not found.
1 pattern(s) tried: ['blog/article/(?P<slug>[-a-zA-Z0-9_]+)/$']
原因と対処:
- URL name の typo:
urls.pyのname='article_detail'と{% url 'article_detail' %}を一致させる - 引数数の不一致: URL パターンが
slugを要求しているのに ID を渡している - namespace 必要:
{% url 'blog:article_detail' slug=art.slug %} - include の app_name:
urls.py冒頭にapp_name = 'blog'
# blog/urls.py
from django.urls import path
from . import views
app_name = 'blog' # namespace
urlpatterns = [
path('article/<slug:slug>/', views.detail, name='article_detail'),
]
# テンプレート
{% url 'blog:article_detail' slug=article.slug %}
# Python コード
from django.urls import reverse
reverse('blog:article_detail', kwargs={'slug': art.slug})
6. CSRF Verification Failed (403)
Forbidden (CSRF token missing or incorrect.):
Reason given for failure: CSRF token missing.
POST フォームには必ず {% csrf_token %} 必要:
<form method="post" action="{% url 'blog:create' %}">
{% csrf_token %} <!-- 必須 -->
<input type="text" name="title">
<button type="submit">送信</button>
</form>
<!-- AJAX の場合 -->
<script>
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
fetch('/api/items/', {
method: 'POST',
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
</script>
HTTPS 環境での追加対処(settings.py):
# Origin 不一致でも 403 になる
CSRF_TRUSTED_ORIGINS = [
'https://example.com',
'https://*.example.com',
]
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
7. DisallowedHost (ALLOWED_HOSTS)
django.core.exceptions.DisallowedHost:
Invalid HTTP_HOST header: 'example.com'.
You may need to add 'example.com' to ALLOWED_HOSTS.# settings.py
ALLOWED_HOSTS = [
'example.com',
'www.example.com',
'.example.com', # サブドメイン全部
'127.0.0.1',
'localhost',
]
# 開発時のみ全許可(本番禁止)
if DEBUG:
ALLOWED_HOSTS = ['*']
8. ImproperlyConfigured
django.core.exceptions.ImproperlyConfigured:
The SECRET_KEY setting must not be empty.
django.core.exceptions.ImproperlyConfigured:
Requested setting DATABASES, but settings are not configured.
You must either define the environment variable DJANGO_SETTINGS_MODULE...
対処:
- SECRET_KEY 未設定:
.envから読込み、 またはsettings.pyに直書き(本番は環境変数推奨) - DJANGO_SETTINGS_MODULE 未設定:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')をmanage.py/wsgi.py冒頭で - NAME 未設定:
DATABASES['default']['NAME']必須
9. ProgrammingError / FieldError
# ProgrammingError: 存在しないカラム参照(マイグレーション漏れ)
django.db.utils.ProgrammingError: column blog_article.summary does not exist
# 対処: makemigrations + migrate
# FieldError: 不正なフィールド指定
django.core.exceptions.FieldError: Cannot resolve keyword 'titel' into field.
Choices are: author, body, category, created_at, id, slug, ...
# 対処: typo 修正 (titel → title)
10. MIGRATION 関連
| 症状 | 対処 |
|---|---|
| You have unapplied migrations | python manage.py migrate |
| Conflicting migrations detected | python manage.py makemigrations --merge |
| Migrations for 'app' not detected | app/migrations/__init__.py がない、 または INSTALLED_APPS 未登録 |
| Inconsistent migration history | DB の django_migrations テーブルと不整合。 環境差分の調査が必要 |
| RemovedInDjangoXX warning | 非推奨機能。 Django アップグレード前に対処 |
11. デプロイ後のエラー
- 500 Internal Server Error: DEBUG=False で詳細が出ない → ログ確認(
/var/log/gunicorn/error.log等) - Static files 404:
collectstatic実行漏れ、 nginx の alias 設定誤り - ImportError: Couldn't import Django: 仮想環境未有効化、 systemd ユニットの
EnvironmentFile誤り - SuspiciousOperation: ALLOWED_HOSTS / SECURE_PROXY_SSL_HEADER 設定漏れ
デバッグのコツ
# 1. DEBUG=True で詳細表示(開発のみ)
DEBUG = True
# 2. django-debug-toolbar
pip install django-debug-toolbar
INSTALLED_APPS += ['debug_toolbar']
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
INTERNAL_IPS = ['127.0.0.1']
# 3. ログ設定
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {'class': 'logging.StreamHandler'},
},
'loggers': {
'django.db.backends': {
'level': 'DEBUG', # 全 SQL ログ
'handlers': ['console'],
},
},
}
# 4. shell でモデル検証
python manage.py shell
>>> from blog.models import Article
>>> Article.objects.all()
# 5. check コマンド
python manage.py check
python manage.py check --deploy # 本番向け追加チェック
FAQ
Q: 本番でエラー詳細を見たい
A: DEBUG=False を維持し、 LOGGING でファイル/Sentry に送る。 DEBUG=True 公開は絶対禁止(SECRET_KEY 漏洩リスク)。
Q: マイグレーション地獄から抜けたい
A: 開発初期なら全削除して作り直し。 運用後は --squash で履歴圧縮。
Q: 全エラーを Sentry に飛ばしたい
A: sentry-sdk をインストールし、 settings.py で sentry_sdk.init()。 リクエスト情報・スタックトレースが自動収集されます。