1-13. DetailViewを使った詳細表示画面の作成

今回のテーマは「DetailViewを使った詳細表示画面の作成」です。前回に引き続きクラスベースビューの使い方を覚えていきましょう。DetailViewは名前の通り詳細情報を表示するビューです。今回は前回リスト表示したトピックの詳細を表示するページを作っていきましょう。

※本ページはDetailViewを使った詳細表示画面の作成まで読まれた方を対象としています。そのためサンプルソースコードが省略されている場合があります。


トピック詳細ページを作る

まずはtemplates/thread/detail_topic.htmlを作成します。
templates/thread/detail_topic.html



{% extends 'base/base.html' %}
{% block title %}トピック作成 - {{ block.super }}{% endblock %}
{% block content %}
<div class="ui grid stackable">
    <div class="eleven wide column">
        <div class="ui breadcrumb">
            <a href="{% url 'base:top' %}" class="section">TOP</a>
            <i class="right angle icon divider"></i>
            <a class="section">{{topic.category.name}}</a>
            <i class="right angle icon divider"></i>
            <a class="active section">{{topic.title}}</a>
        </div>
        <div class="ui segment">
            <div class="content">
                <div class="header"><h3>{{topic.title}}</h3></div>
                <p>{{topic.user_name}} - {{topic.created}}</p>
                <div class="ui secondary segment">
                    <p><pre>{{topic.message}}</pre></p>
                </div>
            </div>
        </div>
    </div>
    {% include 'base/sidebar.html' %}
</div>
{% endblock %}

次にthread/views.pyに追記しましょう。
thread/views.py


from django.shortcuts import render, redirect
from django.views.generic import CreateView, FormView, DetailView

from . models import Topic


class TopicDetailView(DetailView):
    template_name = 'thread/detail.html'
    model = Topic
    context_object_name = 'topic'

非常に簡単ですね。DetailViewはtemplate_nameとmodelに値を渡してあげると、URLで渡されたpk(primary key)に対応したオブジェクトを呼び出してテンプレートに渡してくれます。その際、例えばTopicオブジェクトならばtopicという名前で渡されます。もしテンプレートに渡す名前を指定したい場合はcontext_object_nameで指定します。今回の場合はcontext_object_nameがなくても問題なく機能しますが、できるだけcontext_object_nameは書いたほうが良いと思います。

URLを作成する

ページにアクセスするURLを決めましょう。{domain_root}/thread/{トピックID}というURLでアクセス出来るようにしましょう。

thread/urls.pyを以下のようにします。
thread/urls.py


from django.urls import path

from . import views
app_name = 'thread'

urlpatterns = [
    path('<int:pk>/', views.TopicDetailView.as_view(), name='topic'),
]

ここで<int:pk>がポイントです。URLからpkを渡すことでDetailViewがpkを元にオブジェクトを取得してくれます。

ブラウザで確認してみましょう。localhost:8080/thread/1にアクセスしてます。番号はトピックのIDであればOKです。

さて、ここで読者諸氏はTemplateViewクラスや関数で書いた場合にどうなるか興味があると思いますので、記載例を見てみましょう。

まずTemplateViewで書いた場合です。

thread/views.py(一部抜粋)


from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import CreateView, FormView, DetailView, TemplateView

class TopicTemplateView(TemplateView):
    template_name = 'thread/detail_topic.html'
    
    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx['topic'] = get_object_or_404(Topic, id=self.kwargs.get('pk', ''))
        return ctx

オブジェクトの取得とテンプレートへの受け渡しをget_context_dataをオーバーライドして行う必要があります。この際に、不適切なpkが渡された場合にはNot found 404を返すようにget_object_or_404関数を使用します。これはよく使う手法です。importも忘れないようにして下さいね。また、DetailViewでは自動的に処理されていたpkがself.kwargsから取得している点も注目して下さい。pkから渡されたパラメータはpkに関わらず、このように取り出すことが出来ます。

次に関数ベースで書いた場合ですが、以下例のようになります。

thread/views.py(一部抜粋)


from django.shortcuts import render, redirect, get_object_or_404

def detail_topic(request):
    ctx = {}
    template_name = 'thread/detail_topic.html'
    if request.method == 'GET':
        ctx['topic'] = get_object_or_404(Topic, request.kwargs.get('pk', ''))
        return render(request, template_name, ctx)

特に問題はないと思いますが、pkの取得の仕方が、変わっている点に注意して下さい。
最後に、ここの本題ではないですが、トップページの各トピックへのリンクを修正しておきましょう。

templates/base/top.html(一部抜粋)



<div class="item">
     <div class="content">
         <div class="header">
             <a href="{% url 'thread:topic' pk=topic.id %}"><h4>{{topic.title}}</h4></a>
         </div>
         <div class="meta">
             <span class="name">{{topic.user_name}}</span>
             <span class="date">{{topic.created}}</span>
         </div>
     </div>
 </div>

引数をpk=topic.idで渡しているところがポイントですね。これでトップページから各トピックにアクセスすることが出来るようになりました。

最後に

ここまで初期投入したデータや管理画面から入力したデータを表示することを見てきました。次回からはユーザーがデータを登録できる画面を作っていきますよ。

Sponsored Link


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です