0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Django】CBVの基本メソッド(get_queryset、get_context_data)

Posted at

はじめに

Djangoの汎用ビューを活用する際、get_querysetget_context_dataはデータ処理とテンプレートへのデータ渡しをカスタマイズするために非常に便利なメソッドです。本記事では、具体例を通してこれらのメソッドの使い方を解説します。

get_queryset メソッド

概要

  • 目的: 表示するオブジェクトのクエリセットを定義します。
  • 特徴:
    • フィルタリングやソートのロジックをカスタマイズ可能。
    • デフォルトでは、モデルに関連付けられた全てのオブジェクトを返します。

使用例

ユーザーの検索条件に基づき、Contractsモデルからデータを取得して絞り込む実装を行います。

    def get_queryset(self):
        """
        ユーザーの検索条件に基づいてクエリセットを取得する。
        """
        form = ItemSearchForm(self.request.GET or None)  # フォーム名をマスキング
        if form.is_valid():
            self.request.session['search_data'] = self.request.GET.copy()  # セッションに保存
        else:
            # セッションから検索条件を取得
            initial_data = self.request.session.get('search_data', {})
            form = ItemSearchForm(initial_data)

        queryset = Items.objects.all().order_by(*self.ordering)  # デフォルトクエリセット
        today = timezone.now().date()  # 今日の日付

        if form.is_valid():
            filters = form.cleaned_data
            if filters.get('keyword'):
                queryset = queryset.filter(name__icontains=filters['keyword'])
            if filters.get('category'):
                queryset = queryset.filter(category__name__icontains=filters['category'])
            if filters.get('status'):
                queryset = queryset.filter(status__icontains=filters['status'])

            # 日付フィルタリング
            date_query = Q()
            if filters.get('before'):
                date_query |= Q(start_date__gt=today)
            if filters.get('current'):
                date_query |= Q(start_date__lte=today, end_date__gte=today)
            if filters.get('undefined'):
                date_query |= Q(start_date__isnull=True) | Q(end_date__isnull=True)

            queryset = queryset.filter(date_query)

        return queryset.distinct()

get_context_data メソッド

概要

  • 目的: テンプレートに渡すコンテキストデータを追加または変更します。
  • 特徴:
    • 親クラスのget_context_dataで生成された基本データに追加情報を加える。
    • 動的なデータをテンプレートに渡す際に活用します。

使用例

以下は、検索フォームと契約データの開始日・終了日をテンプレートに渡す実装です。

    def get_context_data(self, **kwargs):
        """
        テンプレートに渡す追加のコンテキストデータを生成。
        """
        context = super().get_context_data(**kwargs)
        initial_data = self.request.session.get('search_data', {
            'before': True,
            'current': True,
            'undefined': True
        })
        context['form'] = ItemSearchForm(initial=initial_data)
        items = context['items']

        # 日付のフォーマットを追加
        for item in items:
            item.formatted_start_date = (
                item.start_date.strftime('%Y/%m/%d') if item.start_date else None
            )
            item.formatted_end_date = (
                item.end_date.strftime('%Y/%m/%d') if item.end_date else None
            )

        return context

実装例全体

class ItemListView(LoginRequiredMixin, OrderedListMixin, ListView):
    template_name = 'item_list.html'
    model = Items  # モデル名をマスキング
    context_object_name = 'items'  # テンプレート内での名前
    paginate_by = 20  # 1ページあたりの表示件数

    def get(self, request, *args, **kwargs):
        if not request.GET:
            search_data = request.session.get('search_data', None)  # セッションからデータ取得
            if search_data:
                query = f"?{urlencode(search_data)}"
                url = reverse('item_list') + query
                return HttpResponseRedirect(url)
            else:
                # デフォルト検索条件
                query = "?keyword=&category=&status=&before=on&current=on&undefined=on"
                url = reverse('item_list') + query
                return HttpResponseRedirect(url)
        return super().get(request, *args, **kwargs)

    def get_queryset(self):
        """
        ユーザーの検索条件に基づいてクエリセットを取得する。
        """
        form = ItemSearchForm(self.request.GET or None)  # フォーム名をマスキング
        if form.is_valid():
            self.request.session['search_data'] = self.request.GET.copy()  # セッションに保存
        else:
            # セッションから検索条件を取得
            initial_data = self.request.session.get('search_data', {})
            form = ItemSearchForm(initial_data)

        queryset = Items.objects.all().order_by(*self.ordering)  # デフォルトクエリセット
        today = timezone.now().date()  # 今日の日付

        if form.is_valid():
            filters = form.cleaned_data
            if filters.get('keyword'):
                queryset = queryset.filter(name__icontains=filters['keyword'])
            if filters.get('category'):
                queryset = queryset.filter(category__name__icontains=filters['category'])
            if filters.get('status'):
                queryset = queryset.filter(status__icontains=filters['status'])

            # 日付フィルタリング
            date_query = Q()
            if filters.get('before'):
                date_query |= Q(start_date__gt=today)
            if filters.get('current'):
                date_query |= Q(start_date__lte=today, end_date__gte=today)
            if filters.get('undefined'):
                date_query |= Q(start_date__isnull=True) | Q(end_date__isnull=True)

            queryset = queryset.filter(date_query)

        return queryset.distinct()

    def get_context_data(self, **kwargs):
        """
        テンプレートに渡す追加のコンテキストデータを生成。
        """
        context = super().get_context_data(**kwargs)
        initial_data = self.request.session.get('search_data', {
            'before': True,
            'current': True,
            'undefined': True
        })
        context['form'] = ItemSearchForm(initial=initial_data)
        items = context['items']

        # 日付のフォーマットを追加
        for item in items:
            item.formatted_start_date = (
                item.start_date.strftime('%Y/%m/%d') if item.start_date else None
            )
            item.formatted_end_date = (
                item.end_date.strftime('%Y/%m/%d') if item.end_date else None
            )

        return context

まとめ

  • get_queryset: ユーザーの検索条件に基づくデータの取得や絞り込みを行います。
  • get_context_data: テンプレートで使用するための追加情報を提供します。

これらのメソッドを適切に活用することで、Djangoビューを柔軟にカスタマイズできます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?