Django REST framework 第三章 CBV

從介紹Django快開始,咱們就一直在使用FBV的方式來撰寫代碼,兩者本質上並無太大的區別,然而到了REST framework,更會傾向於用CBV來寫API的視圖,後面會看到這個方式的強大,它容許咱們重用經常使用的功能,讓代碼更簡練。django

 

Rewriting Our API using class-based view

如今開始撰寫一個簡單的CBV代碼,打開app內的views.py文件app

from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.http import Http404
from app01.models import Snippet
from app01.serializers import SnippetSerializer


class SnippetList(APIView):
    """
    列出全部的對象或者建立一個新的對象
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

很好,很不錯。它如今看起來跟以前的實例仍是很像,可是如今咱們要着手於在不一樣的HTTP方法間更好的分離,來更新一下上述實例的代碼,仍是在app的views.py文件。post

class SnippetDetail(APIView):
    """
    獲取、更新、刪除一個實例對象
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

這段代碼看起來很棒,可是它如今仍是跟FBV的代碼很像。url

同時,還須要稍微重構app內的urls文件,如今須要用CBV的方式。spa

from app01 import views
from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns


urlpatterns = [
    path('snippets/', views.SnippetList.as_view()),
    path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)

 

好了,咱們已經完成了。若是你將代碼容許起來,應該跟以前的效果同樣。rest

 

Using mixins

使用CBV的的最大優勢之一就是,它容許咱們很容易的編寫一些可重用的行爲。code

到目前爲止,建立、刪除、更新、獲取這些操做在任何模型支持的API視圖中都是很是類似的。orm

一塊兒來看下,如何使用mixin類來構建視圖。再次修改view.py文件對象

from app01.models import Snippet
from app01.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics


class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):  # 獲取
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):  # 建立
        return self.create(request, *args, **kwargs)

來花點時間審查一下,到底這裏發生了什麼。首先建立的類使用了GenericAPIView,同時也繼承了ListModelMixinCreateModelMixinblog

基類提供了核心的功能,mixin類提供了.list().create()操做。而後,明確的綁定了getpost方法到合適的行爲。到目前爲止,足夠簡單。

繼續改造另外一個CBV

class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

跟上面的CBV很是類似。一樣的,咱們再一次使用GenericAPIView來提供核心代碼,而後使用mixin中的.retrieve(), .update(), .destory()方法。

 

 

Using generic class-based views

上面使用mixin類使用比以前更少的代碼稍微重寫了視圖,可是咱們還能更上一層樓。REST framework提供了一系列已經混合封裝好的generic視圖,進而能夠直接在views.py文件內簡化使用。

from app01.models import Snippet
from app01.serializers import SnippetSerializer
from rest_framework import generics


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

 

看到這裏,難免會驚歎,OMG!這也太簡潔了。咱們免費獲得了大量的代碼,咱們的代碼看起來很好,很乾淨,很符合語言習慣的Django。

相關文章
相關標籤/搜索