1. 程式人生 > >Django -- DRF 中的 檢視 詳解

Django -- DRF 中的 檢視 詳解

兩個基類的介紹

Ⅰ. APIView
介紹:
APIView是REST framework提供的所有檢視的基類,繼承自Django的View父類。

APIView與View的不同之處在於

  • 傳入到檢視方法中的是REST framework的Request物件,而不是Django的HttpRequeset物件;
  • 檢視方法可以返回REST framework的Response物件,檢視會為響應資料設定(render)符合前端要求的格式;
  • 任何APIException異常都會被捕獲到,並且處理成合適的響應資訊;
  • 在進行dispatch()分發前,會對請求進行身份認證、許可權檢查、流量控制。

案例一:完成所有書籍的展示查詢

繼承於APIView,程式碼實現如下:

#  views.py 部分程式碼
from rest_framework.views import APIView
from rest_framework.response import Response


class BookInfoAPIView(APIView):
    books = BookInfo.objects.all()
    serializer = BookInfoModelSerializer

    def get(self, request):
        s = self.serializer(self.books, many=True)
        return Response(s.data)

#  urls.py 中的 url
url(r'books/', views.BookInfoAPIView.as_view())

Ⅱ. **GenericAPIView**

介紹:
繼承自APIView,增加了對於列表檢視和詳情檢視可能用到的通用支援方法。通常使用時,可搭配一個或多個Mixin擴充套件類。

支援定義的屬性

  1. 列表檢視與詳情檢視通用:
  • queryset 列表檢視的查詢集
  • serializer_class 檢視使用的序列化器
  1. 列表檢視使用:
  • pagination_class 分頁控制類
  • filter_backends 過濾控制後端
  1. 詳情頁檢視使用:
  • lookup_field:查詢單一資料庫物件時使用的條件欄位,預設為’pk’

  • lookup_url_kwarg :查詢單一資料時URL中的引數關鍵字名稱,預設與look_field相同。

提供的方法:

列表檢視與詳情檢視通用:

  • get_queryset : 獲取檢視對應的查詢集,是列表檢視和詳細檢視獲取資料的基礎;預設返回的是queryset 的屬性,可重寫
  • get_serializer_class : 獲取序列化器類,預設返回的是serializer_class,可重寫;
  • get_serializer(self, args, *kwargs) :
    獲取序列化器物件,這一步相對於APIView來說,就免去了建立序列化物件;

詳情檢視使用:

get_object(self) : 返回詳情檢視所需的模型類資料物件,預設使用lookup_field引數來過濾queryset。 在試圖中可以呼叫該方法獲取詳情資訊的模型類物件。

若詳情訪問的模型類物件不存在,會返回404。

該方法會預設使用APIView提供的check_object_permissions方法檢查當前物件是否有許可權被訪問。


案例二:需求:查詢某個書籍的具體資訊

繼承GenericAPIView實現的程式碼:

#  views.py 部分程式碼
class BookInfoAPIView(GenericAPIView):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer

    def get(self, request, pk):
        # 需求: 查詢某個書籍的詳細資訊
        book = self.get_object()
        # 獲取序列化物件
        ser = self.get_serializer(book)

        return Response(ser.data)
#  urls.py 中的 url
url(r'books/(?P<pk>\d+)/$', views.BookInfoAPIView.as_view())

擴充套件類

Ⅲ . 五個擴充套件類

  1. ListModelMixin: 快速實現列表檢視,返回200狀態碼。
    該Mixin的list方法會對資料進行過濾和分頁。
# 查詢所有書籍的資訊
class BookInfoAPIView(ListModelMixin, GenericAPIView):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer

    def get(self, request):
        return self.list(request)
  1. CreateModelMixin: 快速實現建立資源的檢視,成功返回201狀態碼。
    如果序列化器對前端傳送的資料驗證失敗,返回400錯誤。
#  建立資料 
class BookInfoAPIView(CreateModelMixin, GenericAPIView):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer

    def post(self, request):
        return self.create(request)
# urls.py
url(r'books/', views.BookInfoAPIView.as_view())
  1. RetrieveModelMixin: 可以快速實現返回一個存在的資料物件。
    如果存在,返回200, 否則返回404。
class BookInfoAPIView(RetrieveModelMixin, GenericAPIView):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer

    def get(self, request, pk):
        return self.retrieve(request)

# urls.py
url(r'books/(?P<pk>\d+)/$', views.BookInfoAPIView.as_view())
  1. UpdateModelMixin: 更新檢視擴充套件類,提供update(request, *args, **kwargs)方法,可以快速實現更新一個存在的資料物件。
    同時也提供partial_update(request, *args, **kwargs)方法,可以實現區域性更新。
    成功返回200,序列化器校驗資料失敗時,返回400錯誤。
class BookInfoAPIView(UpdateModelMixin, GenericAPIView):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer

    def put(self, request, pk):
        book = self.get_object()

        return self.update(request, book)
  1. DestroyModelMixin: 刪除檢視擴充套件類,提供destroy(request, *args, **kwargs)方法,可以快速實現刪除一個存在的資料物件。
    成功返回204,不存在返回404。

檢視集

Ⅳ . ViewSet 檢視集

常用檢視集的父類

1) ViewSet
繼承自APIView,作用也與APIView基本類似,提供了身份認證、許可權校驗、流量管理等。

在ViewSet中,沒有提供任何動作action方法,需要我們自己實現action方法。

2)GenericViewSet
繼承自GenericAPIView,作用也與GenericAPIVIew類似,提供了get_object、get_queryset等方法便於列表檢視與詳情資訊檢視的開發。

3)ModelViewSet
繼承自GenericAPIVIew,同時包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

4)ReadOnlyModelViewSet
繼承自GenericAPIVIew,同時包括了ListModelMixin、RetrieveModelMixin

action屬性
比如:

urlpatterns = [
url(r’^books/ $ ‘, views.BookInfoViewSet.as_view({‘get’: ‘list’})),
url(r’^books/latest/$ ‘, views.BookInfoViewSet.as_view({‘get’: ‘latest’})),
url(r’^books/(?P\d+)/$ ‘, views.BookInfoViewSet.as_view({‘get’: ‘retrieve’})),
url(r’^books/(?P\d+)/read/$’ , views.BookInfoViewSet.as_view({‘put’: ‘read’})),
]

在檢視集中,我們可以通過action物件屬性來獲取當前請求檢視集時的action動作是哪個

現在以ModelViewSet 做程式碼案例演示:

class BookInfoAPIView(ModelViewSet):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer
# url.py中的urlatterns配置
url(r'books/(?P<pk>\d+)/$', views.BookInfoAPIView.as_view({'get': 'retrieve'})),
url(r'books/', views.BookInfoAPIView.as_view({'get': 'list'}))

在繼承了ModelViewSet之後,我們只要在路由中配置的時候,說明什麼請求對應什麼action,就可以很簡單的完成檢視函式的關於資料庫的簡單的增刪改查。


Ⅴ . 路由router

上面的方式定義路由,相對來說,還是比較繁瑣的,我們現在可以使用更簡單的。

REST framework提供了兩個router:

  • SimpleRouter
  • DefaultRouter

DefaultRouter與SimpleRouter的區別是,DefaultRouter會多附帶一個預設的API根檢視,返回一個包含所有列表檢視的超連結響應資料。

使用方法:

(1):建立router物件,並註冊檢視集

from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'books', BookInfoAPIView, base_name='book')

register(prefix, viewset, base_name)

  • prefix 該檢視集的路由字首
  • viewset 檢視集
  • base_name 路由名稱的字首

(2):新增路由資料到urlpatterns中
有下面兩種方式都可以

urlpatterns = [
    ...
]
urlpatterns += router.urls
urlpatterns = [
    ...
    url(r'^', include(router.urls))
]

路由router形成URL的方式
在這裡插入圖片描述

在這裡插入圖片描述


Ⅵ . 檢視集中定義附加action動作

雖然ModelViewSet給我們提供了很簡單的定義檢視函式的方法,但是,並不能滿足咱們的所有需求,所以我們得需要自己定義action動作。

新增自定義動作需要使用rest_framework.decorators.action裝飾器。

以action裝飾器裝飾的方法名會作為action動作名,與list、retrieve等同。

action裝飾器可以接收兩個引數:

  1. methods: 該action支援的請求方式,列表傳遞
  2. detail: 表示是action中要處理的是否是檢視資源的物件(即是否通過url路徑獲取主鍵)

detail引數:

  • True 表示使用通過URL獲取的主鍵對應的資料物件
  • False 表示不使用URL獲取主鍵
class BookInfoAPIView(ModelViewSet):
    # 定義檢視的查詢集
    queryset = BookInfo.objects.all()
    # 指定檢視對應的序列化器
    serializer_class = BookInfoModelSerializer

    # 自定義action動作
    @action(methods=['get'], detail=False)
    def latest(self, request):
        # 本action是獲取最新的書
        book = BookInfo.objects.latest('id')
        ser = self.get_serializer(book)
        return Response(ser.data)

檢視關係一覽

Ⅶ. 檢視函式繼承關係

這個是從pycharm直接匯出的,可以根據圖示將檢視之間的繼承關係梳理清楚。
在這裡插入圖片描述