概要
以下のListViewを使用したタスク一覧検索処理について、見えない親クラスの処理をざっくりと見える化して全体のどこの処理をオーバーライドしているのかをまとめた。
概要 クラスベースビュー(class-based view)で一覧検索機能を作成したのでまとめた。 一覧検索機能は、Djangoがもともと用意しているListViewクラスを継承してを作成する。 前提 Djang[…]
ListView
ListViewの見えない処理をざっくりと見える化して、オーバーライドして実装する箇所は全体のどこにあたるのかを説明する。
ListViewの実装例
ListViewは例えば以下のように実装する。
todoapps.views.py
class TodoTopView(LoginRequiredMixin, ListView):
"""TODOリスト一覧表示"""
# モデル
model = models.Todo
# テンプレート
template_name = "todo/top.html"
# 一覧データのkey名称
context_object_name = "tasks"
def get_queryset(self):
"""検索条件をオーバーライドする"""
# ステータス0(未完了)かつ期日の昇順で取得
return models.Todo.objects.filter(status=0).order_by("due_date")
GETリクエストの処理概要
細かい内容は割愛して、大きな処理の流れは以下となる。
解説
それぞれの処理について解説する。
全体の流れ
モデル名(model)に設定したテーブルオブジェクトを使用して一覧検索を行う。
一覧検索した結果をコンテキストに設定して、画面テンプレートとコンテキストを組み合わせたHTMLをレスポンスとして返却する。
dispatch()メソッド
ブラウザからのリクエストをもとに、get()メソッドまたはpost()メソッドの呼び出しを制御する。
今回はget()メソッドを呼び出す。
一覧検索処理
オーバーライドしない場合はモデル名に紐づくテーブルを全検索する。
今回はモデル名(model)にmodels.Todoを設定しているため、Todoクラスに紐づくテーブルが検索対象となる。
また、一覧検索処理をオーバーライドしており、ステータスが0(未完了)のデータを検索して期日の昇順でソートして取得している。
コンテキスト設定
検索結果をコンテキストに設定する。
デフォルトでは”object_list”をキーに、一覧データがコンテキストに登録される。
今回はcontext_object_nameフィールドに”tasks”を設定しているため、”tasks”にも紐づいて一覧データがコンテキストに登録される。
※コンテキストとは、画面にサーバーの値を表示させるための辞書データのこと
レスポンス返却
コンテキストとテンプレート名を組み合わせた画面を返却する。
今回はtemplate_nameに”todo/top.html”を設定しているため、”todo/top.html”とコンテキストを組み合わせた画面をレスポンスしている。
処理の補足
ListViewから呼ばれる親クラスについて、どんな処理を実行しているのか紹介する。
getメソッド
getメソッドは以下のような実装になっている。
BaseListView
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty:
# When pagination is enabled and object_list is a queryset,
# it's better to do a cheap query than to load the unpaginated
# queryset in memory.
if self.get_paginate_by(self.object_list) is not None and hasattr(
self.object_list, "exists"
):
is_empty = not self.object_list.exists()
else:
is_empty = not self.object_list
if is_empty:
raise Http404(
_("Empty list and “%(class_name)s.allow_empty” is False.")
% {
"class_name": self.__class__.__name__,
}
)
context = self.get_context_data()
return self.render_to_response(context)
・コンテキスト設定
・レスポンス返却
get_context_dataメソッド
get_context_dataメソッドは以下のような実装になっている。
BaseListView
def get_context_data(self, *, object_list=None, **kwargs):
"""Get the context for this view."""
queryset = object_list if object_list is not None else self.object_list
page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset)
if page_size:
paginator, page, queryset, is_paginated = self.paginate_queryset(
queryset, page_size
)
context = {
"paginator": paginator,
"page_obj": page,
"is_paginated": is_paginated,
"object_list": queryset,
}
else:
context = {
"paginator": None,
"page_obj": None,
"is_paginated": False,
"object_list": queryset,
}
if context_object_name is not None:
context[context_object_name] = queryset
context.update(kwargs)
return super().get_context_data(**context)
・コンテキスト設定(ページング含む)