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/
獲得
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的多個視圖中重用的常見行爲。