サイドバーの「Django ドキュメント検索」というプレースホルダの入った検索では、Django ドキュメント (Django 2.1) の公式サイト内を検索できます
Django チュートリアルの進め方 その 3 (2)

目次

はじめに

Django を学習するには、何はともあれ公式チュートリアル「はじめての Django アプリ作成」からスタートしてみるのが良いでしょう。しかし、いざチュートリアル通りに進めようとしても躓く場合も多いと思います。そこで、「チュートリアルの進め方」シリーズとして、チュートリアルに沿った作業を行いながら補足事項をまとめることにしました。チュートリアルで躓いた際のヒントとしてお使いください。

利用環境は Ubuntu、 Linux Mint を中心として説明しますが、 Windows についても補足します。

前回は、Django チュートリアルの進め方 その 3 (1) と題してはじめての Django アプリ作成、その 3 の前半についてまとめました。

今回は、はじめての Django アプリ作成、その 3 の後半についてまとめました。

404 エラーの送出

detail ビューを記述します。

from django.http import Http404
from django.shortcuts import render

from .models import Question
.
.
.
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})

10行目で get を使って qusetion_id をキーとするデータを取得しようとしています。get は該当するデータが無い場合 DoesNotExist 例外を発生させるため、 12行目で Http404() でエラーを描画させています。

動作を確認するために、仮のビューを作成しておきます。

{{ question }}

ブラウザで http://127.0.0.1:8000/polls/1/ にアクセスしてみます。

id=1 の質問が表示されました。次は存在しない id=2 で試してみます。ブラウザで http://127.0.0.1:8000/polls/2/ を試します。

存在しない id なので 'Page not found (404)' となりました。ただし、メッセージの最後2行にあるように、この画面は DEBUG = True の場合に表示される画面になっています。本番環境でどのような画面になるのか確認してみます。

mysite/settings.py を修正します。

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

ALLOWED_HOSTS = ['*']

DEBUG = False, ALLOWED_HOSTS = ['*'] に設定しました。

デフォルト値: [] (空のリスト)

Django サイトを配信できるホスト/ドメイン名を表す文字列のリスト。

このリスト中の値は完全修飾名(例: 'www.example.com') 、ピリオドで始まる値 (サブドメインのワイルドカードを表す)等を指定。また、 '*' という値はあらゆるヘッダにマッチ (本番では非推奨)。

DEBUG が True かつ ALLOWED_HOSTS が空なら、host は ['localhost', '127.0.0.1', '[::1]'] に対して検証される。

ALLOWED_HOSTS は、テスト時にも検証される。

ブラウザで http://127.0.0.1:8000/polls/2/ を確認します。

セキュリティを守るため、表示される情報量は最小限になっています。確認を終えたら、DEBUG = True, ALLOWED_HOST = [] に戻しておきましょう。

ショートカット: get_object_or_404()


詳細表示で頻出のパターン、オブジェクトが存在しなければ 404エラー、存在した場合はそのオブジェクトを表示、という処理は、get_object_or_404() ショートカットで記述を簡略化できます。

from django.shortcuts import get_object_or_404, render

from .models import Question
.
.
.
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})
.
.
.

get_object_or_404(klass, *args, **kwargs)

与えられたモデル (klass) のマネージャの get() をコールする。モデルの DoesNotExist 例外でなく Http404 例外を投げる。

テンプレートシステムを使う

先程仮に作成した detail ビューのテンプレート (polls/templates/polls/detail.html) を書き換えます。

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

http://127.0.0.1:8000/polls/1/ にアクセスして確認します。

テンプレート内のハードコードされたURLを削除

index のテンプレートの URL ハードコード部分を除去します。

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

polls.urls で name = 'detail' として指定した 'detail' の名前を使って、{% url 'detail' パラメータ %} として detail ビューに対応した URL が自動生成されます。また、<int:question_id> に相当するパラメータを question.id で指定 (テンプレートには question というコンテキストが渡されていますので、ここから id を取得) している事がわかります。

    path('<int:question_id>/', views.detail, name='detail'),

URL 名の名前空間

テンプレート内で {% url %} タグを使って URL を生成する場合、アプリ間で URL に指定した名前の衝突を避けるため、URLconf 内で app_name を使って名前空間を設定します。 polls.urls に名前空間を設定します。

from django.urls import path

from . import views

app_name = 'polls
urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

テンプレートの記述にも名前空間を指定 ('detail' → 'polls:detail' に変更) します。

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

 

URLconf 作成時に app_name を設定しておく事を習慣にしておきましょう。

参考

低価格なのに高速・多機能・高セキュリティ 月額400円(税別)から最大容量100GB WordPress専用高速サーバー Z.com WP
おすすめの記事