drf中的各種view,viewset


drf中的各種view,viewset

Django REST framework里有各種各樣的view,讓我有點蒙,得好好捋一捋這關系。

視圖的作用

Django用“視圖”這個概念封裝處理用戶請求並返回響應的邏輯。

視圖是一個可調用對象,它不僅可以是基於函數,也可以是基於類的。

相比較與函數,基於類的視圖有一些區別和優勢:

  • 組織與特定HTTP方法相關的代碼(GET,POST等) 可以通過單獨的方法而不是條件分支來解決。
  • 面向對象的技術例如Mixin(多繼承、混用)可以將代碼分解成可重用的組件。

視圖函數:

def my_view(request):
    if request.method == 'GET':
        # <view logic>
        return HttpResponse('result')

視圖類:

class MyView(View):
    def get(self, request):
        # <view logic>
        return HttpResponse('result')

View

Django中的View

是所有基於類的view的父類,它負責將視圖連接到URL、HTTP 方法調度(GET,POST等)和其它簡單的功能。

APIView

APIView是drf中所有view的父類,本身繼承於Django的VIew,只有簡單的調度方法和健壯檢查。

和View的不同

  • 請求和返回使用的drf的Request Response而不是django的HttpRequest HttpResponse
  • 請求傳入時進行身份驗證,並在傳給處理方法前進行權限檢驗。
  • 任何APIException都會被捕捉並放入合適的想要中。

使用

response返回的內容需是序列化的json。

先創建在goods包下新建serializer.py

某字段結果可能有多條時,記得加many=True!否則無法正確顯示。

class GoodsSerializer(serializers.ModelSerializer):
    images = GoodImagesSerializer(many=True)
    
    class Meta:
        model = Goods
        fields = "__all__"
	

views

因為會有多條商品信息,所以這里也要記得加many=True!否則會報錯。

class GoodsListView(APIView):
	# 重寫get方法 進行get訪問時會進行的處理
    def get(self, request):
        goods = Goods.objects.all()[:10]
        goods_list = GoodsSerializer(goods, many=True)
        return Response(goods_list.data)		

在url下配置view的訪問,別忘了這是基於類的視圖,所以要加上as_view()方法。

url(r'^GoodsListView/', GoodsListView.as_view()),

GenericAPIView

GenericAPIView繼承於APIView,為標准list和detail詳情提供了常用行為,每個GenericAPIView都會和一個或多個mixin聯合使用。

屬性

  • 基礎設置
    • queryset 需要返回的結果集
    • serializer_class 用於序列化的serializer
    • lookup_field 查找單個model實例時的字段,默認為pk(主鍵)
    • lookup_url_kwarg
  • 分頁
    • pagination_class
  • 過濾
    • filter_backend

使用

先在views里設置個分頁

class StandardResultsSetPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size' # GoodsListView/?p=2&page_size=3
    page_query_param = 'p' # GoodsListView/?p=2
    max_page_size = 100
class GoodsListView(GenericAPIView, ListModelMixin):
    """
    商品列表
    """
    queryset = Goods.objects.all()
    # 序列化
    serializer_class = GoodsSerializer
    # 分頁
    pagination_class = StandardResultsSetPagination
    # 過濾 /排序、搜索
    filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
    ordering_fields = ('add_time', )
    search_fields = ('name', 'goods_desc')

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

ListAPIView

除了繼承GenericAPIView加ListModelMixin,重寫了下get方法,沒干別的事。

源碼

class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
    """
    Concrete view for listing a queryset.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

使用

class GoodsListView(ListAPIView):
    """
    商品列表
    """
    queryset = Goods.objects.all()
    # 序列化
    serializer_class = GoodsSerializer
    # 分頁
    pagination_class = StandardResultsSetPagination
    # 過濾 /排序、搜索
    filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
    ordering_fields = ('add_time', )
    search_fields = ('name', 'goods_desc')

作用就是少寫繼承,不用重寫get...

類似有:

class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView)
class RetrieveAPIView(mixins.RetrieveModelMixin,
                      GenericAPIView)
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                            mixins.UpdateModelMixin,
                            GenericAPIView)

等等常用到的行為都被封裝了。

GenericViewSet

繼承於GenericAPIView,並提供默認的get_object,get_queryset方法和其他通用視圖基本行為,但默認情況下不包含任何操作。為了使用GenericViewSet類,您將覆蓋該類並混合所需的mixin類,或者顯式定義動作實現。

源碼

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass

只是比GenericAPIView多了ViewSetMixin。

在ViewSetMixin里重寫了as_view方法,可以更方便的綁定actions。

使用

class GoodsListViewSet(GenericViewSet, ListModelMixin):
    """
    商品列表
    """
    queryset = Goods.objects.all()
    # 序列化
    serializer_class = GoodsSerializer
    # 分頁
    pagination_class = StandardResultsSetPagination

urls配置

將get請求 綁定到list() action

goods_list = GoodsListViewSet.as_view({
    'get': 'list'
})

urlpatterns = [
	....
    url(r'^goodsList/', goods_list),
]

使用router

VIewSet常常和router使用,router可以自動將常用的 get綁定list,post綁定create這些操作完成。

urls中設置如下,上面的那兩個設置就不需要了。

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('goodsList', GoodsListViewSet)

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

ReadOnlyModelViewSet

繼承於GenericViewSet,混用RetrieveModelMixin,ListModelMixin。這樣我們就既可以用它來訪問列表,也可以用來訪問詳情。

源碼

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    """
    A viewset that provides default `list()` and `retrieve()` actions.
    """
    pass

使用

class GoodsViewSet(viewsets.ReadOnlyModelViewSet):
    """
    商品列表
    商品詳情
    """
    queryset = Goods.objects.all()
    # 序列化
    serializer_class = GoodsSerializer
    # 分頁
    pagination_class = StandardResultsSetPagination
   

綁定router

router.register('goods', GoodsViewSet)

訪問接口


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM