Djangoのよくあるエラーと解決方法まとめ。DisallowedHost・NoReverseMatch・マイグレーション矛盾など

Djangoのよくあるエラーと解決方法まとめ。DisallowedHost・NoReverseMatch・マイグレーション矛盾など

Django開発でよく遭遇するエラーの原因と解決方法を、この記事1本にまとめて解説します。

  1. DisallowedHost(サーバー配置時の定番)
  2. InconsistentMigrationHistory(CustomUser導入時)
  3. NoReverseMatch: ‘XXX’ is not a registered namespace
  4. Generic detail view must be called with either an object pk or a slug
  5. RuntimeWarning: received a naive datetime
  6. [Celery] NotRegistered

1. DisallowedHost

ローカルで開発してきたソースをサーバーへ配置すると、ほぼ確実に遭遇するエラーです。

解決方法

settings.pyALLOWED_HOSTS に、アクセスに使うホスト名(またはIPアドレス)を追記します。

# ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['example.com']

複数指定する場合はカンマ区切り、すべて許可する場合はワイルドカードが使えます。

ALLOWED_HOSTS = ['example.com', '192.0.2.10']
ALLOWED_HOSTS = ['*']   # 開発時のみ。本番では使わない

['*'] はHostヘッダー検証を無効化してしまうため、本番環境では必ず実ホスト名を列挙してください。ローカル・開発・本番でALLOWED_HOSTSを分けたい場合は、settings.pyを環境ごとに分割する方法が便利です。

2. InconsistentMigrationHistory

CustomUserモデルを導入・修正した際に発生します。

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency user.0001_initial on database 'default'.

原因はマイグレーション履歴の矛盾です。DjangoデフォルトのUserモデルで admin のマイグレーションが先に適用されてしまっており、後から導入したCustomUserモデルとの依存関係を追跡できなくなっています。

解決方法:DBの作り直し(推奨)

開発初期であれば、作成済みのDBを削除してマイグレーションをやり直すのが最も確実です。CustomUserモデルはプロジェクトの最初に導入しておくのが定石です。

回避策:adminのコメントアウト(非推奨)

settings.pyurls.py でadminを無効化すれば一応回避できますが、管理画面が使えなくなり、なぜ無効化したのか履歴も追えなくなるためおすすめしません。

INSTALLED_APPS = [
    # 'django.contrib.admin',
    'django.contrib.auth',
    # ...
]

3. NoReverseMatch: ‘XXX’ is not a registered namespace

NoReverseMatch at / 'XXXXX' is not a registered namespace

テンプレートやreverseで {% url 'polls:index' %} のように名前空間つきでURLを参照しているのに、名前空間が登録されていない場合に発生します。

解決方法

アプリの urls.pyapp_name を定義します。

from django.urls import path
from . import views

app_name = 'polls'

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
]

参考: URL名の名前空間(公式チュートリアル)

4. Generic detail view must be called with either an object pk or a slug

Generic detail view XXXXDetailView must be called with either an object pk or a slug in the URLconf.

DetailView(および BaseDetailView)は、URLのパラメータ名として pk または slug しか受け付けません。独自のパラメータ名を使うとこのエラーになります。

解決方法

urls.py のURLパラメータ名を pk に修正します。

# エラーになるパターン
path('detail/<int:app_id>/', XXXXDetailView.as_view(), name='detail'),

# 解消するパターン
path('detail/<int:pk>/', XXXXDetailView.as_view(), name='detail'),

5. RuntimeWarning: received a naive datetime

RuntimeWarning: DateTimeField ItemList.created received a naive datetime

Pythonのdatetimeには、タイムゾーンを持たないnaive持つawareの2種類があります。USE_TZ = True の環境でモデルのDateTimeFieldへnaiveなdatetimeを渡すと、この警告が出ます。

解決方法:django.utils.timezoneを使う

Djangoでは django.utils.timezone でawareなdatetimeを簡単に取得できます。datetime.now() の代わりにこちらを使いましょう。

from django.utils import timezone

now_utc = timezone.now()          # UTC
now_local = timezone.localtime()  # ローカルタイム

標準の datetime パッケージで扱う場合はタイムゾーンを明示します。

import datetime as dt
from zoneinfo import ZoneInfo  # Python 3.9未満は pytz を使用

now_utc = dt.datetime.now(dt.timezone.utc)
now_local = now_utc.astimezone(ZoneInfo('Asia/Tokyo'))

ベストプラクティスはawareで保持し、表示時にシステムごとのタイムゾーンへ変換することです。

6. [Celery] NotRegistered

DjangoでCeleryを使ったタスクを追加した際に、タスクは登録できるのに実行すると次のエラーになることがあります。

{"exc_type": "NotRegistered", "exc_message": ["celery_tasks.tasks.hello"], "exc_module": "celery.exceptions"}

解決方法:WorkerとBrokerの再起動

@shared_task でタスクを追加・変更した後は、CeleryのWorkerとBrokerを再起動してください。Workerは起動時にタスクを読み込むため、起動後に追加されたタスクを認識できず NotRegistered となります。

まとめ

エラー対処
DisallowedHostALLOWED_HOSTS にホスト名を追記
InconsistentMigrationHistoryDBを作り直す(CustomUserは最初に導入)
not a registered namespaceurls.pyapp_name を定義
pk or a slug in the URLconfURLパラメータ名を pk にする
naive datetime警告django.utils.timezone を使う
Celery NotRegisteredWorker/Brokerを再起動

認証まわりの実装はdjango-allauth入門ガイドも参考にしてください。

技術ブログ一覧へ戻る