DRF框架的視圖簡析

首先我們明確REST接口開發的核心任務

在開發REST API接口時,視圖中做的最主要有三件事:

  • 將請求的數據(如JSON格式)轉換爲模型類對象
  • 操作數據庫
  • 將模型類對象轉換爲響應的數據(如JSON格式)

一:使用Django開發REST 接口

數據的獲取和返回格式的組織,都要開發人員自己編寫。返回對象爲HttpResponseJsonResponse等一些子類對象,視圖類繼承自View   

class BooksView(View):
    """
    查詢所有圖書
    """
    def get(self, request):
        """
        查詢所有圖書
        路由:GET /books/
        """
        queryset = BookInfo.objects.all()
        book_list = []
        for book in queryset:
            book_list.append({
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'image': book.image.url if book.image else ''
            })
        return JsonResponse(book_list, safe=False)

附:響應對象要帶上狀態碼201(新建、修改), 204(刪除), 查詢不用加status 會自動返回200(成功)、404(失敗)

 

二:使用Django REST framework(DRF)框架來開發REST接口

想對於Django開發此接口 來看看DRF框架做的逐步封裝簡化

1.序列化器的引入對數據對象進行轉換的操作不再需要開發人員去完成,且包含了對數據的驗證功能。

class BooksView(View):
    """查詢所有圖書信息
    """
    def get(self, request):
        """
        查詢所有圖書
        路由:GET /books/
        """
        books = BookInfo.objects.all()
        book_serializer = BookInfoSerializer(books, many=True)
        book_dict = book_serializer.data
        print(book_dict)
        return JsonResponse(book_dict, safe=False)

2.視圖類的封裝拓展:

2.1)兩個API視圖基類(繼承自Django的View類) [代碼體現在Response的簡便]

"""DRF框架的APIView類、GenericAPIView類,和django中View主要的不同就是請求對象和響應對象不同"""

request:

request.data返回解析之後的請求體數據

request.query_params與Django標準的request.GET相同,獲取查詢字符串。

Response:

REST framework提供了一個響應類Response,使用該類構造響應對象時,響應的具體數據內容會被轉換(render渲染)成符合前端需求的類型, 構造方式如下:

Response(data, status=None, template_name=None, headers=None, content_type=None)

繼承自APIView的視圖代碼:

class BooksAPIView(APIView):
    """查詢所有圖書信息
    """
    def get(self, request):
        """
        查詢所有圖書
        路由:GET /books/
        """
        books = BookInfo.objects.all()
        book_serializer = BookInfoSerializer(books, many=True)
        book_dict = book_serializer.data
        print(book_dict)
        return Response(book_dict)  # safe=False不需要寫了

 

2.2) GenericAPIView類 繼承自APIView,主要增加了操作序列化器和數據庫查詢的方法 [代碼體現在數據的操作和方法的簡便],一般和5個Mixin拓展類配合使用,爲他們提供方法支持。5個擴展類:List、Create、Retrieve、Update、DestroyModelMixin (前面幾個省略一點 :))

from rest_framework.mixins import ListModelMixin
from rest_framework.generics import GenericAPIView

class BooksListView(ListModelMixin, GenericAPIView):
    """只用指明數據模型類queryset
       序列化器serializer_class
       數據的操作也簡化了,不在需要開發人員去進行序列化器的操作了
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request):
        return self.list(request)

2.3) 繼承自Mixin擴展類和GenericAPIView的子類可用視圖 [代碼體現在方法都不用寫了],CreateAPIView、ListAPIView、Retrieve、Update、Destroy、

RetrieveUpdate、RetrieveUpdateDestrop  (後面省略了APIView  :))

from rest_framework.generics import ListAPIView
# ListAPIView 繼承自GenericAPIView, ListModelMixin
class BooksListAPIView(ListAPIView):  # 可使用ListCreateAPIView
    """此時的視圖只用指定兩個屬性,方法都不用寫了
       但是帶pk和不帶pk的還是要分兩個視圖類編寫
    """
    queryset = HeroInfo.objects.all()
    serializer_class = HeroInfoSerializer

2.4) 視圖集ViewSet,使用視圖集,可以將一系列相關的邏輯都放到一個類裏面了 [代碼主要體現在只用寫一個視圖類],不需要再使用兩個視圖類來放不同的邏輯代碼。但是設置路由比較特別

視圖代碼:

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action

class BooksViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,..., GenericViewSet):
    """查詢多個、查詢單個、新增、修改的邏輯都在視圖集裏面所包含"""
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

路由設置:

urlpatterns = [
    url(r'^books/$', views.BooksViewSet.as_view({'get': 'list'})),
    url(r'^books/(?P<pk>\d+)/$', views.BooksViewSet.as_view({'get': 'retrieve'})),
]

2.5) 終極簡便視圖集ModelViewSet [代碼體現在繼承類不用寫那麼多了,但路由的配置也比較特別],繼承自GenericViewSet,同時包括了ListModelMixin、RetrieveModelMixin......

視圖代碼:

from rest_framework.viewsets import ModelViewSet

class BooksModelViewSet(ModelViewSet):
    queryset = HeroInfo.objects.all()
    serializer_class = HeroInfoSerializer

 路由:Routrs

from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'books', BookInfoViewSet, base_name='book')

urlpatterns = [
    ...
]
urlpatterns += router.urls

 register(prefix, viewset, base_name)

  • prefix 該視圖集的路由前綴
  • viewset 視圖集
  • base_name 路由名稱的前綴

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章