1. 程式人生 > 實用技巧 >DRF框架之檢視集、Routers路由

DRF框架之檢視集、Routers路由

先上程式碼:

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from utils.pagination import NewPagination
from .models import Projects
from .serializers import
ProjectsModelSerializer class ProjectsPage(ListCreateAPIView): ''' 類檢視 ''' queryset = Projects.objects.all() serializer_class = ProjectsModelSerializer filter_backends = [DjangoFilterBackend, OrderingFilter] filterset_fields = ['id', 'name', 'leader', 'programmer', 'tester
'] ordering_fields = ['id', 'name', 'leader', 'programmer', 'tester'] pagination_class = NewPagination class ProjectsDetailsPage(RetrieveUpdateDestroyAPIView): queryset = Projects.objects.all() serializer_class = ProjectsModelSerializer

我們現在想將兩個檢視進行合併,要怎麼操作呢?直接合並我們發現有以下痛點:

  • 兩個類檢視不能合併
  • 有兩個相同的get方法
  • 兩個類檢視所對應的url地址不一致

因此這裡引出了檢視集,將檢視集與mixins結合使用,即可解決痛點

一、檢視集

請求方法 動作(action) 描述
GET retrieve 獲取詳情資料(單條)
GET list 獲取列表資料(多條)
POST create 建立資料
PUT update 更新資料
PATCH partail_update 更新部分資料
DELETE destroy 刪除資料

1.ViewSet類

  • 繼承ViewSetMixin和views.APIView
    • ViewSetMixin支援action動作
  • 未提供get_onject()、get_serializer()、queryset、serializer_class等,因此不支援過濾、排序和分頁的操作

2.GenericViewSet類

  • 繼承ViewSetMixin和generic.GenericAPIView
    • 提供get_onject()、get_serializer()、queryset、serializer_class等,支援過濾、排序和分頁的操作
  • 在定義路由時,需要將請求方法與action動作進行繫結
  • 使用Mixin類簡化程式

3.ReadOnlyModelViewSet類

  • 繼承mixins.RetrieveModelMixin、mixins.ListModelMixin和generic.GenericAPIView

4.ModelViewSet類

  • 繼承mixins.CreateModelMixin、mixins.RetrieveModelMixin、mixins.UpdateModelMixin、mixins.DestroyModelMixin、mixins.ListModelMixin和generic.GenericAPIView

開始的程式碼優化如下:

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from utils.pagination import NewPagination
from .models import Projects
from .serializers import ProjectsModelSerializer


class ProjectsPageSet(mixins.ListModelMixin,
                      mixins.CreateModelMixin,
                      mixins.RetrieveModelMixin,
                      mixins.UpdateModelMixin,
                      mixins.DestroyModelMixin,
                      GenericViewSet):
    '''
    類檢視
    '''
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer

    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_fields = ['id', 'name', 'leader', 'programmer', 'tester']
    ordering_fields = ['id', 'name', 'leader', 'programmer', 'tester']
    pagination_class = NewPagination

關於繼承,可以使用ModelViewSet替換所有的繼承:

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework.viewsets import ModelViewSet
from utils.pagination import NewPagination
from .models import Projects
from .serializers import ProjectsModelSerializer


class ProjectsPageSet(ModelViewSet):
    '''
    類檢視
    '''
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer

    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_fields = ['id', 'name', 'leader', 'programmer', 'tester']
    ordering_fields = ['id', 'name', 'leader', 'programmer', 'tester']
    pagination_class = NewPagination

二、Routers路由

  • 檢視類繼承了檢視集之後,支援在定義路由時指定請求方法與action進行對映
  • as_view()需要接收一個字典,key為請求方法名,value為指定需要呼叫的action
from django.contrib import admin
from django.urls import path
from projects.views import ProjectsPageSet


urlpatterns = [
    path('admin/', admin.site.urls),
    path('projects/', ProjectsPageSet.as_view({
        'get': 'list',
        'post': 'create'
    })),
    path('projects/<int:pk>/', ProjectsPageSet.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    }))
]