Chuyển đến nội dung chính

レッスン 6: ビューセット、ルーター、ページネーション

ViewSet (ModelViewSet、ReadOnlyModelViewSet、カスタム アクション)。 DefaultRouter, nested routers. django-filter を使用したページネーションのスタイル、フィルタリング、順序付け。

💻 プログラミング — レッスン 6 レッスン 6: ビューセット、ルーター、ページネーション

Django: 基本から上級まで

パート 2: Django REST フレームワーク

xdev.asia

1. ビューセット

from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    lookup_field = 'slug'

    def get_queryset(self):
        qs = super().get_queryset()
        if self.action == 'list':
            qs = qs.filter(is_active=True)
        return qs

    @action(detail=True, methods=['post'])
    def toggle_active(self, request, slug=None):
        product = self.get_object()
        product.is_active = not product.is_active
        product.save(update_fields=['is_active'])
        return Response({'is_active': product.is_active})

    @action(detail=False)
    def featured(self, request):
        products = self.get_queryset().filter(is_featured=True)[:10]
        serializer = self.get_serializer(products, many=True)
        return Response(serializer.data)

class CategoryViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    lookup_field = 'slug'

2.ルーター

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('products', ProductViewSet, basename='product')
router.register('categories', CategoryViewSet, basename='category')

urlpatterns = [
    path('api/', include(router.urls)),
]
# GET    /api/products/
# POST   /api/products/
# GET    /api/products/{slug}/
# PUT    /api/products/{slug}/
# DELETE /api/products/{slug}/
# POST   /api/products/{slug}/toggle_active/
# GET    /api/products/featured/

3. ページネーション

from rest_framework.pagination import (
    PageNumberPagination,
    LimitOffsetPagination,
    CursorPagination,
)

class StandardPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 100

class CursorProductPagination(CursorPagination):
    page_size = 20
    ordering = '-created_at'

class ProductViewSet(viewsets.ModelViewSet):
    pagination_class = StandardPagination
    ...

4. フィルタリングと順序付け

pip install django-filter
import django_filters
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend

class ProductFilter(django_filters.FilterSet):
    min_price = django_filters.NumberFilter(field_name='price', lookup_expr='gte')
    max_price = django_filters.NumberFilter(field_name='price', lookup_expr='lte')

    class Meta:
        model = Product
        fields = ['category', 'is_active']

class ProductViewSet(viewsets.ModelViewSet):
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_class = ProductFilter
    search_fields = ['name', 'description']
    ordering_fields = ['price', 'created_at', 'name']
    ordering = ['-created_at']

次の記事: 高度なシリアライザーと検証。