アドベント・カレンダー初参加です。よろしくお願いしまーす。
概要
趣味 Pythonista です。今年 Django に入門し、ウェブサイトを作ってみました。今回は自分とおなじ Django 初心者に向けて、最初に頭を悩ませ悲痛な叫びを上げるであろうコトについて攻略法をざっくり書いてみようとおもいます。ズバリ **Server Error (500)**です。
このとき、一時的にでも画面にエラー内容を出したり、ログを出力したり、はたまた Slack にエラー内容を通知したりしてみます。
Server Error (500)発生
初心者なので views.py のメソッドについついバグを仕込んでしまいました。
def index(request):
aaaa # ←突然の aaaa
return HttpResponse('<p>Hello world.</p>')
settings.py の DEBUG
が True
だと、次のようにわかりやすいエラーメッセージが表示されます。
ただし DEBUG
を False
に変えた途端に親の顔より見た Server Error (500)が現れると思います。
この画面を出しているのは handler500
サーバエラーが発生したときのハンドラーが django.conf.urls.__init__.py にありました。
handler500 = defaults.server_error
サーバでエラーが起こると、この handler500 が実行されます。つまり defaults.server_error 関数が実行されます。 django.views.defaults.server_error の中身を覗くと、この画面を出している処理が記述されていますね。
@requires_csrf_token
def server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
"""
500 error handler.
Templates: :template:`500.html`
Context: None
"""
# 中略
return HttpResponseServerError(
ERROR_PAGE_TEMPLATE % {'title': 'Server Error (500)', 'details': ''},
content_type='text/html',
)
だったら handler500 に代入する関数を defaults.server_error ではなく違う関数にしてしまえばいいんですね。
handler500 に違う関数を代入する
- 自前の server_error 関数を定義
- handler500 にそれを代入
自前の server_error は views.py に定義してみます。オリジナルのやつが django.views.defaults に定義してあるので。
@requires_csrf_token
def my_customized_server_error(request, template_name='500.html'):
return HttpResponseServerError('<h1>Server Error (500)だよー</h1>')
handler500 への代入は urls.py で行います。オリジナルの handler500 の定義は django.conf.urls にあるので。
handler500 = views.my_customized_server_error
Server Error 画面の変更をすることができました。
あとはもう、 my_customized_server_error に好きなこと書けばいいですね。
my_customized_server_error の例
普通に print
するコードです。
@requires_csrf_token
def my_customized_server_error(request, template_name='500.html'):
import traceback
print(traceback.format_exc())
return HttpResponseServerError('<h1>Server Error (500)だよー</h1>')
DEBUG = True
のときと同じエラー画面を出すコードです。これ見やすいですよね。(小並感)
@requires_csrf_token
def my_customized_server_error(request, template_name='500.html'):
import sys
from django.views import debug
error_html = debug.technical_500_response(request, *sys.exc_info()).content
return HttpResponseServerError(error_html)
親の顔より見たデフォルトの Server Error (500)画面を出すコードです。先程見つけ出した django.views.defaults.server_error を使えば OK です。
@requires_csrf_token
def my_customized_server_error(request, template_name='500.html'):
from django.views.defaults import server_error
return server_error(request, template_name)
みんな大好き Slack に通知を飛ばすコードです。
@requires_csrf_token
def my_customized_server_error(request, template_name='500.html'):
import requests
import json
import traceback
requests.post(
'あなたの Slack Webhook URL',
data=json.dumps({
'text': '\n'.join([
f'Request uri: {request.build_absolute_uri()}',
traceback.format_exc(),
]),
'username': 'Django エラー通知',
'icon_emoji': ':jack_o_lantern:',
})
)
return HttpResponseServerError('<h1>Server Error (500)だよー</h1>')
飛びました。私のぱそこのディレクトリ構成が表示されてしまうので、モザイクを入れさせてもらっちゃいます。
明日の Django アドベント・カレンダーは @boxboxbax さんです。がんばってください!