django のエラーハンドリングのメモ。
やりたいこと
- エラー発生時にエラーをログに出力
- エラー発生時に独自のレスポンスを返却
準備
app1 というアプリケーションで 'api/' で json を返却する API を作成します。
django-admin startproject app1
cd app1
python manage.py startapp api
プログラム例
urls.py
urls.py 内に handlerXXX に独自のエラーハンドラを設定します。
app1/urls.py
from api.views import hello, error
from .views import error_handler400, error_handler404, error_handler500
urlpatterns = [
path('api/hello/', hello),
path('api/error/', error),
]
handler400 = error_handler400
handler404 = error_handler404
handler500 = error_handler500
エラーハンドラ
上記の urls.py に指定した error_handlerXXX を app1/views.py に定義しました。
stderr とログファイルにログを出力するようにしています。
app1/views.py
import sys
import traceback
from django.http import JsonResponse
def error_handler400(request, exception):
sys.stderr.write(f"{__name__} error\n")
sys.stderr.write(f"traceback:\n{traceback.format_exc()}\n")
return JsonResponse({"status": 400, "message": "bad request"}, status=400)
def error_handler404(request, exception):
sys.stderr.write(f"{__name__} error\n")
sys.stderr.write(f"traceback:\n{traceback.format_exc()}\n")
return JsonResponse({"status": 404, "message": "not found"}, status=404)
def error_handler500(request):
sys.stderr.write(f"{__name__} error\n")
sys.stderr.write(f"traceback: {traceback.format_exc()}\n")
return JsonResponse({"status": 500, "message": "internal server error"}, status=500)
API 例
api/views.py
import sys
from django.http import JsonResponse
def hello(request):
sys.stderr.write(f"hello()\n")
return JsonResponse({"message": "Hello"})
def error(request):
sys.stderr.write(f"error()\n")
raise Exception('error')
return JsonResponse({"message": "Hello"})
実行例
サーバ起動
python manage.py runserver
API へのアクセス (エラーなし)
リクエスト
curl 'http://127.0.0.1:8000/api/hello/'
レスポンス
{"message": "Hello"}
stderr
hello()
API へのアクセス (エラー発生)
/api/error/ では raise で例外を発生させていますので、エラーハンドラの error_handler500() でエラーが返却されます。
リクエスト
curl 'http://127.0.0.1:8000/api/error/'
レスポンス
{"status": 500, "message": "internal server error"}
エラーハンドラでは stderr にログを出力しています。
stderr
error()
error1.views error
traceback: Traceback (most recent call last):
File ".../site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File ".../site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../app1/api/views.py", line 15, in error
raise Exception('error')
Exception: error