💡

DjangoのDetailViewに関して

2024/08/23に公開

DjangoのDetailViewのまとめ

すぐに忘れてしまうので、DetailViewについて備忘録としてまとめておく

公式サイトのDetailViewの説明

https://docs.djangoproject.com/ja/5.1/ref/class-based-views/generic-display/#detailview

DetailViewのコード

GitHubのDetailViewのコードです。バージョン5.1です

https://github.com/django/django/blob/5.1/django/views/generic/detail.py

DetialView

DetailViewはDjangoの組み込みViewです。DetailViewを継承したViewにおいて、1件のオブジェクトを表示するために利用します。テンプレートに1個のオブジェクトを保持するデータをわたします

簡単に言うと、指定したモデルクラスを1件だけ表示します

DetailViewの前提としてURL

urls.pyでパス変数を設定します。int:pkを指定します。URLでわたされた主キー値のレコードを表示します

urls.py
from django.urls import path
from . import views

app_name = "study"

urlpatterns = [
    path('monster/detail/<int:pk>', views.MonsterDetailView.as_view(), name="monster_detail"),
]

簡単なDetailView

基本形です

  • 「model」はモデル名として「Monster」を指定します。未設定の場合、「queryset」を指定するか、「get_queryset」メソッドのオーバーライドが必要です
  • template_nameではテンプレートファイルを指定します。デフォルトでは、「モデル名_detail.html」になります。アプリ名とモデル名でディレクトリ分割したいのでディレクトリで区切ります
  • テンプレートで利用するquerysetは初期設定で「object」です
views.py
from django.views.generic import DetailView
from .models import Monster

class MonsterDetailView(DetailView):
  model = Monster
  template_name = "study/monster/detail.html"

テンプレートファイル

対応するテンプレートファイルです。

  • base.htmlを作成して、継承します
  • django_bootstarap5を利用します
  • Bootstrap5でスタイリングします
  • データを保持する変数名は「object」です
  • 一覧のURL:study:monster_list
  • 新規作成のURL:study:monster_create
  • 更新のURL:study:monster_update
study/monster/list.html
{% extends "base.html" %}

{% load django_bootstrap5 %}

{% block title%}{{ title }}{% endblock %}

{% block content %}
<div class="container mt-4">
    <h2 class="mb-4 p-2 bg-primary text-white">{{ title }}</h2>

    <div class="mb-3">
        <a href="{% url 'study:monster_list' %}" class="btn btn-primary">一覧に戻る</a>
    </div>
    
    <table class="table table-bordered table-hover">
        <tr>
            <th>ID</th>
            <td>{{object.id}}</td>
        </tr>
        <tr>
            <th>名前</th>
            <td>{{object.name}}</td>
        </tr>
        <tr>
            <th>HP</th>
            <td>{{object.hp}}</td>
        </tr>
        <tr>
            <th>MP</th>
            <td>{{object.mp}}</td>
        </tr>
        <tr>
            <th>TYPE</th>
            <td>{{object.get_type_display}}</td>
        </tr>
        <tr>
            <th>BIRTHDAY</th>
            <td>{{object.birthday}}</td>
        </tr>
    </table>
</div>
{% endblock %}

querysetを指定する

modelを指定しないで、querysetを指定します。querysetには、1行の処理しか記述できません。基本的には、modelで指定するほうが簡単。

views.py
class MonsterDetailView(DetailView):
  queryset = Monster.objects.all()
  template_name = "study/monster/detail.html"

get_querysetをオーバーライドする

model, querysetを指定しないで、get_querysetメソッドをオーバーライドします。modelを指定するほうが簡単

views.py
class MonsterDetailView(DetailView):
  template_name = "study/monster/detail.html"
  
  def get_queryset(self):
    return Monster.objects.all()

get_objectをオーバーライドする

get_objectをオーバーライドすることで、表示したいデータを自由に操作可能です。通常は、modelで指定したモデルからパス変数でわたされた値のレコードを検索して取り出します。get_objectを利用すると表示するデータを自在に変更できます。戻り値はモデルインスタスです。QuerySetではないです

views.py
class MonsterDetailView(DetailView):
  model = Monster
  template_name = "study/monster/detail.html"
  
  def get_object(self):
    object = Monster.objects.get(id=5)
    return object

コンテキストにデータを渡す

get_context_dateメソッドをオーバーライドすることで、コンテキストに追加データを渡すことができます。つまり、テンプレートで利用するデータを指定します

views.py
class MonsterDetailView(DetailView):
  model = Monster
  template_name = "study/monster/detail.html"
  
  def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context["title"] = self.__class__.__name__
    return context

継承元クラス

以下のクラスを継承しています

django.views.generic.detail.SingleObjectTemplateResponseMixin
django.views.generic.base.TemplateResponseMixin
django.views.generic.detail.BaseDetailView
django.views.generic.detail.SingleObjectMixin
django.views.generic.base.View

メソッドの実行順序

setup()
dispatch()
http_method_not_allowed()
get_template_names()
get_slug_field()
get_queryset()
get_object()
get_context_object_name()
get_context_data()
get()
render_to_response()

Discussion