概要
以下のDetailViewを使用したタスク詳細処理について、見えない親クラスの処理をざっくりと見える化してどのような流れで詳細データを取得しているのかをまとめた。
概要 クラスベースビュー(class-based view)で詳細画面表示機能を作成したのでまとめた。 詳細画面表示機能は、Djangoがもともと用意しているDetailViewクラスを継承して作成する。 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リクエストの処理概要
細かい内容は割愛して、大きな処理の流れは以下となる。
解説
それぞれの処理について解説する。
全体の流れ
クエリパラメータを取得して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に検索結果データが格納される。