Djangoのモデルに該当するデータがないときに404ページを返す方法
|
Djangoで、例えばURLにプライマリキーを含ませて、viewでそのプライマリキーを変数として受け取る。
そしてその変数でDBに検索をかけて、該当するカラムの情報を抜き出す。というのをやりたいとき。
それは次のようなコードで実現できるかなと思います。
user = User.objects.get(id=id)
しかし上記のコードだけだと、該当するレコードがない場合は Does not exist というエラーが返ってしまいます。
該当するレコードがない場合は404ページを返して、よしなに処理したいというのをやってみました。
ユースケース
Userというモデルを用意し、プロフィールページでUserの情報を表示する。という想定です。
- ユーザーはブラウザから、Userのプライマリキーを含んだURLを叩く
- Djangoのviewでプライマリキーを変数として受け取る
- 受け取った変数をキーにUserモデルの情報を探す
- 有ればそのデータを、無ければ404ページをユーザーへ返す
urls.py
URLに変数を含む時の書き方。 uuid:id の部分で変数を受け取り、views.pyへ渡します。
...
path('users/<uuid:id>/', views.profile, name='profile'),
...
*…Userモデルのプライマリキーをuuidとなるように設定していたため、ここでは uuid:id と記述しています。
views.py…方法①
filter()とexists()メソッドを使う方法です。
filter()でフィルターをかけ、exists()で存在すればTrue、無ければFalseが返るので、それを分岐条件にします。
from django.http import Http404
def profile(request, id):
if User.objects.filter(pk=id).exists():
user = User.objects.get(pk=id)
context = {
'user': user,
}
return render(request, 'myapp/profile.html', context)
else:
raise Http404("No User matches the given query.")
views.py…方法②
見つからなかった場合「DoesNotExist」というエラーが返ることがわかっているので、try-except構文でよしなに処理すれば良いのかなと。
from django.http import Http404
def my_view(request, id):
try:
user = User.objects.get(pk=id)
context = {
'user': user,
}
return render(request, 'myapp/profile.html', context)
except User.DoesNotExist:
raise Http404("No User matches the given query.")
views.py…方法③
get_object_or_404()というメソッドを使う方法です。
これが一番スマートですね。動き的には、方法②と同等の処理をしているようです。
from django.shortcuts import get_object_or_404
def profile(request, id):
user = get_object_or_404(User, pk=id)
context = {
'user': user,
}
return render(request, 'myapp/profile.html', context)
まとめ
これでよしなに処理できます。やったね!
404ページをカスタマイズして表示する方法もあるそうな。でも面倒なので気が向いた時に頑張ります。