Python | Django | Viewを利用したエラーページへの対処方法

2021年7月19日

公開日:2021/7/19

Pythonには,DjangoというWebアプリケーションフレームワークがある.フレームワークのため,Djangoを利用するとWebアプリを通常よりも短時間で開発することが可能になる.

前記事にて,「Viewを利用したリダイレクトの実装方法」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「Viewを利用したエラーページへの対処方法」を以下6つの構成にて記す.

  1. 404エラー表示の変更
  2. 404エラー画面の作成
  3. 意図的な404エラー発生方法
  4. 500エラー発生と表示の変更方法
  5. “get_object_or_404″を利用した404エラー対処方法
  6. “get_list_or_404″を利用した404エラー対処方法

◆実施環境

Python 3.8.8
Django 3.2.3

■Viewを利用したエラーページへの対処方法

  1. 404エラー表示の変更

現状,ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する(移行方法の詳細はこちら).その後以下のように”python manage.py runserver”を実行する.実行後,以下が出力される.

(djangoenv) C:\Users\shiro\Desktop\210517_python development\myviewtest\viewproject
>python manage.py runserver

System check identified no issues (0 silenced). # 以下出力箇所
July 18, 2021 - 14:42:56
Django version 3.2.3, using settings 'viewproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

“http://127.0.0.1:8000/"をクリックし,ブラウザで以下ページが開く.

“viewproject/settings.py"を以下のように編集する.

DEBUG = False # 以下変更箇所
ALLOWED_HOSTS = ['127.0.0.1']

再度,"http://127.0.0.1:8000/"をクリックし,ブラウザで開くと以下ページが表示される.

  1. 404エラー画面の作成

“restaurant/views.py"に追記し,以下のように編集する.

from django.shortcuts import render, redirect
from .models import Menus

def menu_list(request):
  menus = Menus.objects.all()
  return render(request, 'restaurant/menu_list.html',context={
    'menus':menus
  })

def menu_detail(request, id):
  menu_de = Menus.objects.filter(pk=id).first()
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception): # 以下追記箇所
  return render(request, 'restaurant/404.html', status=404)

“viewproject/templates/restaurant"に"404.html"を作成する.プロジェクトの構成は以下のようになる.

“404.html"は以下のように編集する.

<h2>ページが見つかりません</h2>
<a href="{% url 'restaurant:menu_list' %}">メニューリストへ!</a>

“viewproject/urls.py"に追記し,以下のように編集する.

from django.contrib import admin
from django.urls import path, include
from restaurant import views # 追記箇所

urlpatterns = [
  path('admin/', admin.site.urls),
  path('restaurant/', include('restaurant.urls')),
]

handler404 = views.error_404page # 追記箇所

上記を保存し,"http://127.0.0.1:8000/"をクリックし,ブラウザで開くと,"404.html"で設定した以下ページが表示される.

ターミナルには以下のように"404″が出力される.

[18/Jul/2021 15:35:21] 
"GET / HTTP/1.1" 404 108

“http://127.0.0.1:8000/"の後ろに適当な文字を入力しても,以下ページが表示される.

ターミナルには,以下のように,URLの後ろに記述した文字と共に,"404″が出力される.

[18/Jul/2021 15:35:50] 
"GET /fajisdfjaof HTTP/1.1" 404 108

上記の"メニューリストへ!"をクリックすると,以下ページに遷移する.

  1. 意図的な404エラー発生方法

“restaurant/views.py"に追記し,以下のように編集する."http://127.0.0.1:8000/restaurant/menu_detail/"の後ろに"id"である"100″を記述するとエラーページに遷移するように実装する.

from django.shortcuts import render, redirect
from .models import Menus
from django.http import Http404 # 追記箇所

def menu_list(request):
  menus = Menus.objects.all()
  return render(request, 'restaurant/menu_list.html',context={
    'menus':menus
  })

def menu_detail(request, id):
  if id == 100: # 追記箇所(12~13行目)
    raise Http404
  menu_de = Menus.objects.filter(pk=id).first()
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception):
  return render(request, 'restaurant/404.html', status=404)

上記を保存し,実際に"http://127.0.0.1:8000/restaurant/menu_detail/100″を入力すると,以下ページに遷移した.

比較として,idが存在する範囲内(idが1~4)を入力するとメニュー詳細ページに遷移する.以下はid=1であるページ"http://127.0.0.1:8000/restaurant/menu_detail/1″を入力すると,以下ページに遷移する.

idが存在する範囲外,すなわちid=6であるページ"http://127.0.0.1:8000/restaurant/menu_detail/6″を入力すると,自動的に以下ページ(“http://127.0.0.1:8000/restaurant/menu_list/")に遷移する.

  1. 500エラー発生と表示の変更方法

“restaurant/views.py"に追記し,以下のように編集する."menu_list.html"を"menulist.html"に変更することで,"http://127.0.0.1:8000/restaurant/menu_list/"にアクセスすると,存在しないファイルが参照される.以上より,500エラーを発生させることができる.

from django.shortcuts import render, redirect
from .models import Menus
from django.http import Http404

def menu_list(request):
  menus = Menus.objects.all()
  return render(request, 'restaurant/menulist.html',context={ # 編集箇所(menu_list => menulist)
    'menus':menus
  })

def menu_detail(request, id):
  if id == 100:
    raise Http404
  menu_de = Menus.objects.filter(pk=id).first()
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception):
  return render(request, 'restaurant/404.html', status=404)

“http://127.0.0.1:8000/restaurant/menu_list/"にアクセスすると,以下のように500エラーを発生させることができた.

“restaurant/views.py"に追記し,以下のように編集する.

from django.shortcuts import render, redirect
from .models import Menus
from django.http import Http404

def menu_list(request):
  menus = Menus.objects.all()
  return render(request, 'restaurant/menulist.html',context={
    'menus':menus
  })

def menu_detail(request, id):
  if id == 100:
    raise Http404
  menu_de = Menus.objects.filter(pk=id).first()
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception):
  return render(request, 'restaurant/404.html', status=404)

def error_500page(request): # 以下追記箇所
return render(request, 'restaurant/500.html', status=500)

“viewproject/templates/restaurant"に"500.html"を作成する.以下がプロジェクトの構成になる.

“500.html"を以下のように編集する.

<h2>サーバーエラーです</h2>
<a href="{% url 'restaurant:menu_list' %}">メニューリストへ!</a>

“viewproject/urls.py"に追記し,以下のように編集する.

from django.contrib import admin
from django.urls import path, include
from restaurant import views # 追記箇所

urlpatterns = [
  path('admin/', admin.site.urls),
  path('restaurant/', include('restaurant.urls')),
]

handler404 = views.error_404page
handler500 = views.error_500page # 追記箇所

上記を保存し,"http://127.0.0.1:8000/restaurant/menu_list/"にアクセスすると,以下のように編集済みの500エラーを発生させることができた.

  1. “get_object_or_404″を利用した404エラー対処方法

“restaurant/views.py"を変更し,以下のように編集する."get_object_or_404″を利用する.

from django.shortcuts import render, redirect, get_list_or_404, get_object_or_404 # 変更箇所
from .models import Menus
from django.http import Http404

def menu_list(request):
  menus = Menus.objects.all()
  return render(request, 'restaurant/menu_list.html',context={ # 変更箇所(menulist => menu_list)
    'menus':menus
  })

def menu_detail(request, id):
  if id == 100:
    raise Http404
  menu_de = get_object_or_404(Menus, pk=id) # 変更箇所
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception):
  return render(request, 'restaurant/404.html', status=404)

def error_500page(request):
return render(request, 'restaurant/500.html', status=500)

上記を保存すると,"http://127.0.0.1:8000/restaurant/menu_list/"にアクセスしても500エラーにならず,以下のようにメニューリストに遷移するように戻した.

“http://127.0.0.1:8000/restaurant/menu_detail/"の後ろのidが1~4はページが存在するが,それ以外,すなわちid=12であるページ"http://127.0.0.1:8000/restaurant/menu_detail/12″を入力すると,404エラーのページに遷移する.

ターミナルには以下のように"404″が出力される.

[19/Jul/2021 00:21:18] 
"GET /restaurant/menu_detail/12 HTTP/1.1" 404 108
  1. “get_list_or_404″を利用した404エラー対処方法

現状,"http://127.0.0.1:8000/restaurant/menu_list/"にアクセスすると以下ページが表示される.

“restaurant/views.py"を変更し,以下のように編集する."get_list_or_404″を利用する.550kcal超のメニューだけ表示するように実装する.

from django.shortcuts import render, redirect, get_list_or_404, get_object_or_404
from .models import Menus
from django.http import Http404

def menu_list(request):
  menus = Menus.objects.all()
  menus = get_list_or_404(Menus, kcal__gt=550) # 追記箇所
  return render(request, 'restaurant/menu_list.html',context={
    'menus':menus
  })

def menu_detail(request, id):
  if id == 100:
    raise Http404
  menu_de = get_object_or_404(Menus, pk=id)
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception):
  return render(request, 'restaurant/404.html', status=404)

def error_500page(request):
return render(request, 'restaurant/500.html', status=500)/

上記を保存し,"http://127.0.0.1:8000/restaurant/menu_list/"にアクセスすると以下ページが表示される.カロリーが500kcalのペペロンチーノが表示されなくなった.

“restaurant/views.py"を変更し,以下のように編集する."get_list_or_404″を利用して,何も表示されない850kcal超のメニューだけ表示するように実装する.

from django.shortcuts import render, redirect, get_list_or_404, get_object_or_404
from .models import Menus
from django.http import Http404

def menu_list(request):
  menus = Menus.objects.all()
  menus = get_list_or_404(Menus, kcal__gt=850) # 変更箇所
  return render(request, 'restaurant/menu_list.html',context={
    'menus':menus
  })

def menu_detail(request, id):
  if id == 100:
    raise Http404
  menu_de = get_object_or_404(Menus, pk=id)
  if menu_de is None:
    return redirect('restaurant:menu_list')
  return render(request, 'restaurant/menu_detail.html', context={
    'menu_de':menu_de
  })

def forward_website(request):
  return redirect('https://www.shelokuma.com')

def forward_menu(request):
  return redirect('restaurant:menu_detail', id=2)

def error_404page(request, exception):
  return render(request, 'restaurant/404.html', status=404)

def error_500page(request):
return render(request, 'restaurant/500.html', status=500)/

上記を保存し,"http://127.0.0.1:8000/restaurant/menu_list/"にアクセスすると以下ページが表示される.

ターミナルには以下のように"404″が出力される.

[19/Jul/2021 01:02:17] 
"GET /restaurant/menu_list/ HTTP/1.1" 404 108

■参照

https://docs.djangoproject.com/en/3.2/ref/views/#error-views

https://docs.djangoproject.com/en/3.2/topics/http/shortcuts/

以上