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)
訪問接口
-
訪問商品列表
-
訪問商品詳情