1. 程式人生 > >【DRF檢視】

【DRF檢視】

目錄

請結合【DRF序列化】此文獻中的資料檔案及序列化檔案來閱讀如下程式碼.

DRF檢視為我們提供了非常簡便的方法——內建了增刪改查等一系列的操作.
我們只需在url中指定對應的方法,檢視繼承內建方法的類,即可實現兩三行程式碼搞定一個請求.

@
*
我們先看看仿照內建方法實現的**

APIView檢視檔案:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin



""" ===================== 一層封裝 ===================== """


class GenericAPIView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self):
        """用於獲取queryset的方法"""
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        """用於呼叫序列化類的方法"""
        return self.serializer_class(*args, **kwargs)


class ListModelMixin():
    """用於返回get請求所有資料的資料"""
    def list(self, request):
        queryset = self.get_queryset()  # self呼叫的方法(get_queryset)是從執行此方法(list)的當前物件的類中開始找
        ser_obj = self.get_serializer(queryset, many=True)  # 原理同上句話
        return Response(ser_obj.data)


class CreateModelMixin():
    """用於處理post請求發來的資料"""
    def create(self, request):
        ser_obj = self.get_serializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class RetrieveModelMixin():
    """用於返回get請求查詢單條資料方法"""
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(book_obj)
        return Response(ser_obj.data)


class UpdateModelMixin():
    """用於處理put請求發來的資料(更新資料)"""
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class DestroyModelMixin():
    """用於刪除單條資料"""
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        if book_obj:
            book_obj.delete()
            return Response('')
        return Response('The deleted object does not exist.')



""" ===================== 二層封裝 ===================== """


class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass

檢視檔案:

from .custom_mixin import ListCreateAPIView, RetrieveUpdateDestroyAPIView  # 匯入上述的APIView檢視檔案
from DRFView import models
from .serializers import BookSerializer  # 匯入自定義的序列化檔案


class Book(ListCreateAPIView):
    queryset = models.Book.objects.all()  # 坑:這裡的queryset只是放到快取裡了,再次取時還需要用.all()方法
    serializer_class = BookSerializer

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

    def post(self, request):
        return self.create(request)


class BookEdit(RetrieveUpdateDestroyAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

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

    def put(self, request, id):
        return self.update(request, id)

    def delete(self, request, id):
        return self.destroy(request, id)

改進版

urls.py檔案:

urlpatterns = [
    url(r'^book/$', BookModel.as_view({'get': 'list', 'post': 'create'})),
    url(r'^book/(?P<id>\d+)/$', BookModelView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
"""
注意as_view的傳參:
as_view({"請求方式": "呼叫的方法"}, {...})
指定請求方式呼叫的方法後,框架會為我們自動執行其方法,無需在CBV中寫請求的方法了.
"""

APIView檢視檔案:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin  # 匯入DRF封裝好的APIView


""" ===================== 第一層封裝 ===================== """


class GenericAPIView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self):
        """用於獲取queryset的方法"""
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        """用於呼叫序列化類的方法"""
        return self.serializer_class(*args, **kwargs)


class ListModelMixin():
    """用於返回get請求所有資料的資料"""
    def list(self, request):
        queryset = self.get_queryset()  # self呼叫的方法(get_queryset)是從執行此方法(list)的當前物件的類中開始找
        ser_obj = self.get_serializer(queryset, many=True)  # 原理同上句話
        return Response(ser_obj.data)


class CreateModelMixin():
    """用於處理post請求發來的資料"""
    def create(self, request):
        ser_obj = self.get_serializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class RetrieveModelMixin():
    """用於返回get請求查詢單條資料方法"""
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(book_obj)
        return Response(ser_obj.data)


class UpdateModelMixin():
    """用於處理put請求發來的資料(更新資料)"""
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class DestroyModelMixin():
    """用於刪除單條資料"""
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        if book_obj:
            book_obj.delete()
            return Response('')
        return Response('The deleted object does not exist.')



""" ===================== 第二層封裝 ===================== """


class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass



""" ===================== 第三層封裝 ===================== """


class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
# ViewSetMixin重寫了as_view方法,即可以傳參了.
    pass

檢視檔案:

from .custom_mixin import ModelViewSet  # 匯入上述的APIView檢視檔案
from DRFView import models
from .serializers import BookSerializer  # 匯入自定義的序列化檔案


class BookModel(ModelViewSet):
    queryset = models.Book.objects.all()  
    # 坑:這裡的queryset只是放到快取裡了,再次取時還需要用.all()方法
    # queryset是框架能識別的,會把資料放到快取中,如果該成其它的名字則不會快取(比如query),即再此取資料時不能加.all()
    serializer_class = BookSerializer


class BookModelView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

接下來,我們再來看看DRF為我們封裝好了的APIView用法。
***

開始使用內建檢視

第一步 按照框架的要求寫url

urlpatterns = [
    url(r'^book/$', BookModel.as_view({'get': 'list', 'post': 'create'})),
    # 按照APIView的要求,這裡必須寫為pk,而不能寫id
    url(r'^book/(?P<pk>\d+)/$', BookModelView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
"""
注意as_view的傳參:
as_view({"請求方式": "呼叫的方法"}, {...})
指定請求方式呼叫的方法後,無需在CBV中寫請求的方法了.
"""

第二步 寫檢視檔案
```python
from DRFView import models
from .serializers import BookSerializer # 匯入自定義的序列化檔案
from rest_framework.viewsets import ModelViewSet # 匯入DRF封裝好的APIView

class BookModel(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookSerializer

class BookModelView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookSerializer

如上步驟,我們的檢視只要寫兩行就可以了.

關於DRF檢視原始碼解析,推薦參考此文獻:https://www.cnblogs.com/GGGG-XXXX/articles/9675911.html

繼承順序圖解:
在這裡插入圖片描述