Django REST framework-API指南05-ViewSets 原創翻譯

python技術交流羣332680349,資源分享,技術交流。

視圖集合

路由確定哪個控制器用於請求後,您的控制器負責瞭解請求併產生適當的輸出。
…..Ruby on Rails文檔

Django REST框架允許您將一組相關視圖的邏輯組合在一個類中,稱爲 ViewSet。在其他框架中,您也可以在概念上找到名爲“資源”或“控制器”的類似實現。

ViewSet類只是一種類型的基於類的視圖,即不提供任何方法的處理程序,例如,而是提供.get()或.post()操作,代替如.list()和.create()。

使用.as_view()該方法,處理程序ViewSet僅限於完成視圖時的相應操作。

通常,而不是在urlconf中的視圖集中顯式註冊視圖,您將用路由器類註冊一個視圖,該類將自動爲您確定urlconf。

實例

我們定義一個簡單的視圖集,可用於列出或檢索系統中的所有用戶。

from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving users.
    """
    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)

如果我們需要,我們可以將這個視圖集綁定到兩個單獨的視圖中,如下所示:

user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})

通常我們不會這樣做,而是用路由器註冊視圖,並允許自動生成urlconf。

from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'users', UserViewSet, base_name='user')
urlpatterns = router.urls

您經常希望使用提供默認行爲的現有基類,而不是編寫自己的視圖。例如:

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset for viewing and editing user instances.
    """
    serializer_class = UserSerializer
    queryset = User.objects.all()

使用ViewSet類比使用View類有兩個主要優點。

  • 重複的邏輯可以組合成一個類。在上面的例子中,我們只需要指定queryset一次,就可以在多個視圖中使用。
  • 通過使用路由器,我們不再需要處理配置自己的URL。
    權衡利弊。使用常規視圖和URL confs更加明確,併爲您提供更多的控制。如果您想要快速啓動並運行View API,或者當您有一個較大的API,並且您想要一致地執行一致的URL配置時,ViewSets將非常有用。

爲路由標記臨時的操作

REST框架中包含的默認路由器將爲標準的create / retrieve / update / destroy樣式操作,如下所示:

class UserViewSet(viewsets.ViewSet):
    """
    Example empty viewset demonstrating the standard
    actions that will be handled by a router class.

    If you're using format suffixes, make sure to also include
    the `format=None` keyword argument for each action.
    """

    def list(self, request):
        pass

    def create(self, request):
        pass

    def retrieve(self, request, pk=None):
        pass

    def update(self, request, pk=None):
        pass

    def partial_update(self, request, pk=None):
        pass

    def destroy(self, request, pk=None):
        pass

如果您需要路由到特殊方法,則可以將其標記爲需要使用@detail_route或@list_route修飾符的路由。

該@detail_route裝飾包含pk在URL模式,旨在爲需要的單個實例方法。該@list_route裝飾適用於那些對象的名單上操作的方法。

例如:

from django.contrib.auth.models import User
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset that provides the standard actions
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @detail_route(methods=['post'])
    def set_password(self, request, pk=None):
        user = self.get_object()
        serializer = PasswordSerializer(data=request.data)
        if serializer.is_valid():
            user.set_password(serializer.data['password'])
            user.save()
            return Response({'status': 'password set'})
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    @list_route()
    def recent_users(self, request):
        recent_users = User.objects.all().order('-last_login')

        page = self.paginate_queryset(recent_users)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(recent_users, many=True)
        return Response(serializer.data)

裝飾器可以額外收取僅爲路由視圖設置的額外參數。例如…

  @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
    def set_password(self, request, pk=None):
       ...

這些裝飾器將GET默認路由請求,但也可以通過使用methods參數來接受其他HTTP方法。例如:

    @detail_route(methods=['post', 'delete'])
    def unset_password(self, request, pk=None):
       ...

然後,這兩個新的動作可以在網址^users/{pk}/set_password/users/pk/unsetpassword/
獲得

API參考

視圖集合

將ViewSet類繼承APIView。您可以使用任何標準屬性,例如permission_classes,authentication_classes以便在視圖集上控制API策略。

本ViewSet類不提供任何操作實現。爲了使用ViewSet類,您將覆蓋類並明確定義操作實現。

類的視圖集合

GenericViewSet繼承GenericAPIView,並提供了默認設置get_object,get_queryset方法及其他通用視圖基於的行爲,但不包括默認情況下,任何動作。

爲了使用GenericViewSet類,您將覆蓋該類,並混合所需的mixin類,或明確定義操作實現。

模型的視圖集合

ModelViewSet類繼承GenericAPIView,幷包括用於各種方法實現方式,通過在各種混入類的行爲混合。

由ModelViewSet類提供的動作是.list(),.retrieve(), .create(),.update(),.partial_update(),和.destroy()。

例如

因爲ModelViewSet擴展GenericAPIView,通常需要至少提供queryset和serializer_class屬性。例如:

class AccountViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for viewing and editing accounts.
    """
    queryset = Account.objects.all()
    serializer_class = AccountSerializer
    permission_classes = [IsAccountAdminOrReadOnly]

請注意,您可以使用由GenericAPIView提供的任何標準屬性或方法覆蓋。例如,要使用它ViewSet來動態地確定它應該操作的查詢集,你可能會這樣做:

class AccountViewSet(viewsets.ModelViewSet):
    """
    A simple ViewSet for viewing and editing the accounts
    associated with the user.
    """
    serializer_class = AccountSerializer
    permission_classes = [IsAccountAdminOrReadOnly]

    def get_queryset(self):
        return self.request.user.accounts.all()

請注意,queryset屬性從您的ViewSet中刪除後,任何關聯的路由器將無法自動導出模型的base_name,因此您必須指定base_namekwarg作爲路由器註冊的一部分。

另請注意,雖然此類默認情況下提供了完整的create / list / retrieve / update / destroy操作,但您可以使用標準權限類來限制可用的操作。

只讀模型視圖集合

ReadOnlyModelViewSet繼承GenericAPIView。與此同時ModelViewSet它還包括各種操作的實現,但不同的是ModelViewSet僅提供“只讀”操作,.list()以及.retrieve()。

例如

與ModelViewSet一樣,您通常需要至少提供queryset和serializer_class屬性。例如:

class AccountViewSet(viewsets.ReadOnlyModelViewSet):
    """
    A simple ViewSet for viewing accounts.
    """
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

同樣,與之一樣ModelViewSet,您可以使用可用的任何標準屬性和方法覆蓋GenericAPIView

自定義視圖集合基類

您可能需要提供沒有全部ModelViewSet操作的自定義ViewSet類,或以其他方式自定義行爲。

實例

要創建基礎視圖集類,提供create,list和retrieve操作,繼承GenericViewSet和混入所需的操作:

from rest_framework import mixins

class CreateListRetrieveViewSet(mixins.CreateModelMixin,
                                mixins.ListModelMixin,
                                mixins.RetrieveModelMixin,
                                viewsets.GenericViewSet):
    """
    A viewset that provides `retrieve`, `create`, and `list` actions.

    To use it, override the class and set the `.queryset` and
    `.serializer_class` attributes.
    """
    pass

通過創建自己的基本ViewSet類,您可以提供可以跨API的多個視圖中重用的常見行爲。

發佈了48 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章