【Django】クラスベースビューの補足:DetailViewの見えない処理と仕組みについて

概要

以下のDetailViewを使用したタスク詳細処理について、見えない親クラスの処理をざっくりと見える化してどのような流れで詳細データを取得しているのかをまとめた。

あわせて読みたい

概要 クラスベースビュー(class-based view)で詳細画面表示機能を作成したのでまとめた。 詳細画面表示機能は、Djangoがもともと用意しているDetailViewクラスを継承して作成する。 DetailViewをど[…]

【Django】クラスベースビュー(class-based view):DetailViewを使用した詳細画面表示機能の実装_アイキャッチ画像

 

DetailView

DetailViewの見えない処理をざっくりと見える化して、処理の流れを説明する。
尚、DetialViewはGETのみとなるためPOST処理の流れはない。

DetailViewの詳細

DetailViewを使用したタスク詳細表示機能は例えば以下のように実装する。

todoapps.views.py


class TodoDetailView(LoginRequiredMixin, DetailView):	
    """TODO詳細画面表示"""	
	
    # DB参照モデル	
    model = models.Todo	
    # テンプレート	
    template_name = "todo/detail.html"	
    # コンテキスト名の変更	
    context_object_name = "todo"	

 

GETリクエストの処理概要

細かい内容は割愛して、大きな処理の流れは以下となる。

【Django】クラスベースビューの補足:DetaiViewの見えない処理と仕組みについて_GETリクエスト
▲GET処理の流れ

 

解説

それぞれの処理について解説する。

全体の流れ

クエリパラメータを取得してDB検索する。
検索結果をコンテキストに設定する。
画面テンプレートとコンテキストを組み合わせたHTMLをレスポンスする。

 

dispatch()メソッド

ブラウザからのリクエストをもとに、get()メソッドまたはpost()メソッドの呼び出しを制御する。
今回はget()メソッドを呼び出す。

 

データ検索処理

クエリパラメータをもとに、model名に設定したテーブルオブジェクトからレコードデータを取得する。

 

コンテキスト設定

検索結果をコンテキストに設定する。
デフォルトでは”object”をキーに、検索結果データがコンテキストに登録される。
今回はcontext_object_nameフィールドに”todo”を設定しているため、”todo”にも紐づいて検索結果データがコンテキストに登録される。
※コンテキストとは、画面にサーバーの値を表示させるための辞書データのこと

 

レスポンス返却

コンテキストとテンプレート名を組み合わせた画面を返却する。
今回はtemplate_nameに”todo/detail.html”を設定しているため、”todo/detail.html”とコンテキストを組み合わせた画面をレスポンスしている。

 

処理の補足

DetailViewから呼ばれる親クラスについて、どんな処理を実行しているのか紹介する。

getメソッド

getメソッドは以下のような実装になっている。

BaseDetailView


class BaseDetailView(SingleObjectMixin, View):	
    """A base view for displaying a single object."""	
	
    def get(self, request, *args, **kwargs):	
        self.object = self.get_object()	
        context = self.get_context_data(object=self.object)	
        return self.render_to_response(context)	

検索結果を取得して、コンテキストに設定してレスポンスするという流れ。

 

get_objectメソッド

get_objectメソッドは以下のような実装になっている。

SingleObjectMixinクラス


def get_object(self, queryset=None):	
    """	
    Return the object the view is displaying.	
	
    Require `self.queryset` and a `pk` or `slug` argument in the URLconf.	
    Subclasses can override this to return any object.	
    """	
    # Use a custom queryset if provided; this is required for subclasses	
    # like DateDetailView	
    if queryset is None:	
        queryset = self.get_queryset()	
	
    # Next, try looking up by primary key.	
    pk = self.kwargs.get(self.pk_url_kwarg)	
    slug = self.kwargs.get(self.slug_url_kwarg)	
    if pk is not None:	
        queryset = queryset.filter(pk=pk)	
	
    # Next, try looking up by slug.	
    if slug is not None and (pk is None or self.query_pk_and_slug):	
        slug_field = self.get_slug_field()	
        queryset = queryset.filter(**{slug_field: slug})	
	
    # If none of those are defined, it's an error.	
    if pk is None and slug is None:	
        raise AttributeError(	
            "Generic detail view %s must be called with either an object "	
            "pk or a slug in the URLconf." % self.__class__.__name__	
        )	
	
    try:	
        # Get the single item from the filtered queryset	
        obj = queryset.get()	
    except queryset.model.DoesNotExist:	
        raise Http404(	
            _("No %(verbose_name)s found matching the query")	
            % {"verbose_name": queryset.model._meta.verbose_name}	
        )	
    return obj	

 

if pk is not None:
    queryset = queryset.filter(pk=pk)

クエリパラメータのpk(プライマリキー)を取得して、検索条件にセットしている。

 

try:
    # Get the single item from the filtered queryset
    obj = queryset.get()
except queryset.model.DoesNotExist:
    raise Http404(
    _("No %(verbose_name)s found matching the query")
    % {"verbose_name": queryset.model._meta.verbose_name}
    )
return obj

上記のobjに検索結果データが格納される。

 

スポンサーリンク