DEV Community

kaede
kaede

Posted on

Django Tutorial Part 8 -- データがない時に 404 のページを出すようにする

何をするか

https://docs.djangoproject.com/en/4.0/intro/tutorial03/#raising-a-404-error

polls/views.py/detail で URL から渡された id のデータがない時に 404 のページを返すようにする。

現状存在しない id で detail を見るとどうなるか

Image description

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)
Enter fullscreen mode Exit fullscreen mode

現状は、request として URL から渡された question_id をそのまま ページで表示することになっている

よって、存在しない id でもエラーが出ない。


question id に基づく question と detail.html を読み込むようにする。

def detail(request, question_id):
    question = Question.objects.get(pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})
Enter fullscreen mode Exit fullscreen mode

ここから question_id に基づいてテーブルのレコードを取ってきて
polls/template/polls/detail.html を読み込み、context として question を渡すようにする

<h1>Question Detail</h1>
<h2>Question Text</h2>
{{ question }}
Enter fullscreen mode Exit fullscreen mode

Image description

そしてファイルを作成すると、detail で id に基づいた question_text が読める。


try except raise 無しで存在しない question_id にアクセスする

Image description

これでは try except を書いていないので、データがない question_id
にアクセスすると DoesNotExist at /polls/5/ のエラーページが出てしまう


Http404 を使って Question.DoesNotExist で 404 とエラーの詳細を表示する

from django.http import HttpResponse, Http404

def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})
Enter fullscreen mode Exit fullscreen mode

Http404 のライブラリをインポートして
try に先ほどの処理を書いて
except で Question.DoesNotExist の条件で
Http404 と raise で
その Question のレコードがないと言うメッセージを返す。

Image description

これでレコードがない question_id にアクセスすると
404 と表示して、詳細なエラーの原因を表示できるようになる。

ここに 404 Page として HTML も設定できるのだろうか?要検証

Image description

GitHub の 404 は可愛い。


get_object_or_404 を使って try except を省略して処理を書く。

https://docs.djangoproject.com/en/4.0/intro/tutorial03/#a-shortcut-get-object-or-404

    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
Enter fullscreen mode Exit fullscreen mode

この正常と例外に分かれているコードを

    question = get_object_or_404(Question, pk=question_id)
Enter fullscreen mode Exit fullscreen mode

この一行で同じようにかける。

Question.DoesNotExist の条件や、Question does not exist のメッセージは詳しく指定できないが

Image description

No Question matches the given query.

(question_id = 5 と言う) クエリにマッチした Question が見つからなかったと言うメッセージで返してくれる。

try と except で書いた方が丁寧で正確だと思うが、
手早く書くならこれでもありだと思った。


まとめ

def detail(request, question_id):
    question = Question.objects.get(pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})
Enter fullscreen mode Exit fullscreen mode

TableName.objects.get でレコードを取ってくるときは、
中身がないと DoesNotExist のエラーがそのまま出る

try-except raise で

    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
Enter fullscreen mode Exit fullscreen mode

Http404 を使えば
条件に応じた例外処理とエラーメッセージで
404 のページが出せる。

    question = get_object_or_404(Question, pk=question_id)
Enter fullscreen mode Exit fullscreen mode

get_object_or_404 を使うとレコードがなかったときに、
query にマッチしなかったと言うメッセージで 404 のページが出せる。

Top comments (0)