GenericAPIViewとDRFの分頁・フィルタリング機能の活用

GenericAPIView

DRF(Django REST framework)におけるGenericAPIViewは、共通の処理を抽象化し、ビューの実装を簡素化するための基底クラスです。主に以下の機能を提供します:

  • クエリセットのフィルタリング
  • データの分頁処理
  • APIビューの共通メソッドの提供

以下はGenericAPIViewの基本的な構造を示したコードです:

from rest_framework import views, pagination, filters

class CustomGenericAPIView(views.APIView):
    filter_backends = []
    pagination_class = pagination.PageNumberPagination

    def filter_queryset(self, queryset):
        for backend in self.filter_backends:
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset

    @property
    def paginator(self):
        if not hasattr(self, '_paginator'):
            self._paginator = self.pagination_class()
        return self._paginator

    def paginate_queryset(self, queryset):
        return self.paginator.paginate_queryset(queryset, self.request, view=self)

    def get_paginated_response(self, data):
        return self.paginator.get_paginated_response(data)

DRF組み込み分頁クラスの利用

DRFではPageNumberPaginationおよびLimitOffsetPaginationという2つの基本的な分頁クラスを提供しています。

PageNumberPaginationの利用

ページ番号でデータを取得する分頁方式です。

# ...\luffyapi\luffyapi\apps\course\course_pagination.py
from rest_framework import pagination

class CustomPageNumberPagination(pagination.PageNumberPagination):
    page_size = 10
    page_query_param = 'page'
    page_size_query_param = 'size'
    max_page_size = 50

LimitOffsetPaginationの利用

取得するデータの開始位置(offset)と件数(limit)を指定する分頁方式です。

class CustomLimitOffsetPagination(pagination.LimitOffsetPagination):
    default_limit = 10
    limit_query_param = 'limit'
    offset_query_param = 'start'
    max_limit = 100

フィルタリングの実装

組み込みフィルタの使用

DRFではSearchFilterとOrderingFilterを標準で提供しており、以下のように使用します:

from rest_framework import viewsets, filters
from . import models, serializers

class CourseViewSet(viewsets.ModelViewSet):
    queryset = models.Course.objects.all()
    serializer = serializers.CourseSerializer
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['title']
    ordering_fields = ['price', 'created_at']

django-filterによる高度なフィルタリング

インストール:

pip install django-filter

設定:

INSTALLED_APPS += ['django_filters']
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

FilterSetの定義

from django_filters import FilterSet, NumberFilter
from . import models

class CourseFilterSet(FilterSet):
    price_min = NumberFilter(field_name='price', lookup_expr='gte')
    price_max = NumberFilter(field_name='price', lookup_expr='lte')

    class Meta:
        model = models.Course
        fields = ['category', 'instructor']

ビューでの使用

from rest_framework import viewsets
from . import models, serializers, filtersets
from django_filters.rest_framework import DjangoFilterBackend

class CourseViewSet(viewsets.ModelViewSet):
    queryset = models.Course.objects.all()
    serializer_class = serializers.CourseSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = filtersets.CourseFilterSet

カスタムフィルタの実装

class CustomCourseFilter:
    def filter_queryset(self, request, queryset, view):
        category = request.query_params.get('custom_category')
        if category:
            queryset = queryset.filter(category_id=category)
        return queryset

# ビューでの適用
class CourseViewSet(CustomGenericAPIView):
    filter_backends = [CustomCourseFilter]

タグ: DRF Django rest-framework pagination filters

6月13日 22:07 投稿