目錄
視圖家族
視圖類(views)
APIView
- 擁有view的所有功能
- 重寫as_view,局部禁用csrf
- 重寫dispatch
- 一系類列屬性(局部全局配置)
GenericAPIView
該類下主要使用:get_object, get_query, get_serializer
- 繼承APIView,所以擁有APIView的所有
- get_queryset方法,配置queryset類屬性,提供視圖類相關的Models
- 在第二條基礎上,get_object方法,配置lookup_url_kwarg類屬性,提供視圖類相關的具體Model
- get_serializer方法,配置serializer_class類屬性,提供視圖類相關的序列化對象
單查群查
from rest_framework.generics import GenericAPIView
class CarGenericAPIView(GenericAPIView):
#該返回值一定要是query對象,如果object后面不加.query方法,是manager對象
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
# 源碼中默認設置路由參數名lookup_url_kwarg為pk,可以自定義
lookup_url_kwarg = 'pk'
#群查
def get(self,request,*args,**kwargs):
car_query = self.get_queryset()
car_ser = self.get_serializer(car_query,many=True)
return APIResponse(results=car_ser.data)
#單查
def get(self,request,*args,**kwargs):
# pk = kwargs.get('pk')
# car_obj = models.Car.objects.filter(is_delete=False).filter(pk=pk).first()
# car_ser = serializers.CarModelSerializer(car_obj)
car_obj = self.get_object()
car_ser = self.get_serializer(car_obj)
return APIResponse(results=car_ser.data)
視圖工具類(mixins)
CreateModelMixin
ListModelMixin
RetrieveModelMixin
UpdateModelMixin
DestroyModelMixin
單查群查(RetrieveModelMixin,ListModelMixin)
from rest_framework.mixins import RetrieveModelMixin,ListModelMixin
#mixins視圖工具類
class CarReadGenericAPIView(ListModelMixin,RetrieveModelMixin,GenericAPIView):
#該返回值一定要是query對象,如果object后面不加.query方法,是manager對象
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
# 源碼中默認設置路由參數名lookup_url_kwarg為pk,可以自定義
lookup_url_kwarg = 'pk'
#群查
def get(self,request,*args,**kwargs):
response = self.list(request,*args,**kwargs)
return APIResponse(results=response.data)
#單查
def get(self,request,*args,**kwargs):
# car_obj = self.get_object()
# car_ser = self.get_serializer(car_obj)
# return APIResponse(results=car_ser.data)
response = self.retrieve(request, *args, **kwargs)
return APIResponse(results=response.data)
單增(CreateModelMixin)
from rest_framework.mixins import RetrieveModelMixin,ListModelMixin,CreateModelMixin
#mixins視圖工具類
class CarReadGenericAPIView(ListModelMixin,RetrieveModelMixin,CreateModelMixin,GenericAPIView):
#該返回值一定要是query對象,如果object后面不加.query方法,是manager對象
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
# 源碼中默認設置路由參數名lookup_url_kwarg為pk,可以自定義
lookup_url_kwarg = 'pk'
#單增
def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs)
#--------------------------------------------------------
#單增時需要設置哪些字段是需要參與反序列化(子序列化無法完成反序列化)
class SponsorModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Sponsor
fields = ('name', 'phone')
class CarModelSerializer(serializers.ModelSerializer):
# sponsors = SponsorModelSerializer(many=True) # 用子序列化完成外鍵,外鍵就不能參與反序列化
class Meta:
model = models.Car
fields = ('name', 'price', 'brand_name', 'sponsor_list', 'brand', 'sponsors')
extra_kwargs = {
'brand': {
'required': True,
'write_only': True
},
'sponsors': {
'required': True,
'write_only': True
},
}
九大工具視圖類(generics)
ListCreateAPIView(群查和單增)
RetrieveAPIView(單查)
RetrieveDestroyAPIView(單查單刪)
RetrieveUpdateAPIView(單查單改)
RetrieveUpdateDestroyAPIView(單查,單改,單刪)
UpdateAPIView(單改)
單查接口(RetrieveAPIView)
在RetrieveAPIView類內有get方法,該方法封裝了單查方法
#Generics工具視圖類
#單獨完成單查接口
from rest_framework.generics import RetrieveAPIView
class CarRetrieveAPIView(RetrieveAPIView):
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
lookup_url_kwarg = 'pk'
群查接口(ListAPIView)
在ListAPIView類內有get方法,該方法封裝了群查方法
#單獨完成單查接口
from rest_framework.generics import ListAPIView
class CarListAPIView(ListAPIView):
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
RetrieveUpdateDestroyAPIView(單查,單整體改,單局部改,單刪接口)
#單查(get)、單整體改(put)、單局部改(patch)、單刪接口(delete)
from rest_framework.generics import RetrieveUpdateDestroyAPIView
class CarRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
generics類總結
-
APIView
- 擁有view的所有功能
- 重寫as_view,局部禁用csrf
- 重寫dispatch
- 一系類列屬性(局部全局配置)
-
GenericAPIView
- 繼2承APIView,所以擁有APIView的所有
- get_queryset方法,配置queryset類屬性,提供視圖類相關的Models
- 在第二條基礎上,get_object方法,配置lookup_url_kwarg類屬性,提供視圖類相關的具體Model
- get_serializer方法,配置serializer_class類屬性,提供視圖類相關的序列化對象
''' 總結: GenericAPIView就是在APIView基礎上額外提供了三個方法,三個類屬性,如果不配合視圖工具類,體現不出優勢 目的: 視圖中的增刪改查邏輯相似,但操作的資源不一致,操作資源就是操作 資源對象們、資源對象以及資源相關的序列化類, 將這三者形成配置,那操作邏輯就一致,就可以進行封裝 '''
-
mixins視圖工具類們:五個類,六個方法
''' 要配合GenericAPIView類使用,將單查、群查、單增,單整體改,單局部改,單刪六個接口 封裝成retrieve、list、create、update、partial_update、destroy六個方法 原因: 六個方法的實現體,調用的方法就是GenericAPIView提供的,所以要配合GenericAPIView類使用 '''
-
generics工具視圖類們:九種組合
- 幫我們將不同個數不同種類的mixins與GenericAPIView進行組合
- 不同的組合幫我們實現好對應的get、post、put、patch、delete方法
- 需要我們自己配置三個類屬性即可:queryset、serializer_class、lookup_url_kwarg
視圖集(viewsets)
兩個視圖集基類:GenericViewSet和ViewSet
兩個視圖集子類:ReadOnlyModelViewSet,ModelViewSet
一個工具類
ViewSetMixin
在ViewSetMixin類中重寫了as_view方法,將as_view中的參數(方法名)直接映射稱對應的函數,並執行
單查群查共存
#單查群查共存
from rest_framework.viewsets import ViewSetMixin,GenericViewSet,ViewSet
class CarReadOnlyAPIView(RetrieveModelMixin,ListModelMixin,GenericViewSet):
# def many_get(self,request,*args,**kwargs):
# return self.list(request,*args,**kwargs)
#
# def single_get(self,request,*args,**kwargs):
# return self.retrieve(request,*args,**kwargs)
#路由中,直接反射list和retrieve方法
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
六大接口
#路由配置
url(r'^v7/cars/$', views.CarModelViewSet.as_view({
'get': 'list',
'post': 'create',
'put': 'many_update',
'patch': 'many_partial_update',
'delete': 'many_destroy',
})),
url(r'^v7/cars/(?P<pk>\d+)/$', views.CarModelViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy',
})),
# 六大接口
class CarModelViewSet(ModelViewSet):
queryset = models.Car.objects.filter(is_delete=False).all()
serializer_class = serializers.CarModelSerializer
原生視圖集不合理點
'''
分析:
1)沒有群增,群整體改,群局部改,群刪四個接口
2)刪除操作視圖集默認走的destroy方法是將資源從數據庫中刪除,通常一個做字段is_delete字段修改表示刪除
3)響應的結果只有數據,沒有數據狀態碼和狀態信息
'''
解決1
# 群整體改,群局部改,全刪三個接口可以獨立成三個方法
def many_update(self, request, *args, **kwargs):
return APIResponse(msg='這個地方是群整體改,你會寫!')
def many_partial_update(self, request, *args, **kwargs):
return APIResponse(msg='這個地方是群局部改,你會寫!')
def many_destroy(self, request, *args, **kwargs):
return APIResponse(msg='這個地方是群刪,你會寫!')
# 群增與單增必須公用一個接口,都要走create方法 - 重寫create方法,用邏輯進行拆分
def create(self, request, *args, **kwargs):
request_data = request.data
if isinstance(request_data, list):
car_ser = self.get_serializer(data=request_data, many=True)
car_ser.is_valid(raise_exception=True)
car_obj = car_ser.save()
return APIResponse(msg='群增成功', results=self.get_serializer(car_obj, many=True).data)
return super().create(request, *args, **kwargs)
解決2
# destroy方法是完成is_delete字段值修改 - 重寫destroy方法,自定義實現體
def destroy(self, request, *args, **kwargs):
car_obj = self.get_object()
car_obj.is_delete = True
car_obj.save()
return APIResponse(msg='刪除成功')
解決3
# 讓群查有狀態碼和狀態信息 - 重寫list方法
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
return APIResponse(results=response.data)
路由層
# 路由層:
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('v7/cars', views.CarModelViewSet, basename='car')
router.register('books', views.BookModelViewSet, basename='book')
router.register('users', views.UserModelViewSet, basename='user')
urlpatterns = [
'''
url(r'^v7/cars/$', views.CarModelViewSet.as_view({
'get': 'list',
'post': 'create',
'put': 'many_update',
'patch': 'many_partial_update',
'delete': 'many_destroy',
})),
url(r'^v7/cars/(?P<pk>\d+)/$', views.CarModelViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy',
})),
'''
#分發
url(r'', include(router.urls))
]
視圖總結
'''
核心:視圖集都繼承了 ViewSetMixin類,該類重寫了as_view方法,相比APIView的as_view方法,額外多出了一個參數actions
as_view({'get': 'list'}) 傳入的{'get': 'list'}就被actions接收,原理是將get請求映射給視圖類的list函數進行處理
1)為什么有GenericViewSet和ViewSet兩個視圖集基類
GenericViewSet(ViewSetMixin, GenericAPIView),該分支嚴格滿足資源接口
ViewSet(ViewSetMixin, APIView),該分支滿足的接口與資源Model類關系不是特別密切:登錄接口、短信驗證碼接口
2)ReadOnlyModelViewSet,ModelViewSet兩個視圖集子類,就是做個一堆mixin與GenericViewSet相結合,
自己在urls文件中配置as_view設置映射關系
'''