rest_framework(六)


視圖家族

視圖類(views)

APIView

  1. 擁有view的所有功能
  2. 重寫as_view,局部禁用csrf
  3. 重寫dispatch
  4. 一系類列屬性(局部全局配置)

GenericAPIView

該類下主要使用:get_object, get_query, get_serializer

  1. 繼承APIView,所以擁有APIView的所有
  2. get_queryset方法,配置queryset類屬性,提供視圖類相關的Models
  3. 在第二條基礎上,get_object方法,配置lookup_url_kwarg類屬性,提供視圖類相關的具體Model
  4. 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類總結

  1. APIView

    1. 擁有view的所有功能
    2. 重寫as_view,局部禁用csrf
    3. 重寫dispatch
    4. 一系類列屬性(局部全局配置)
  2. GenericAPIView

    1. 繼2承APIView,所以擁有APIView的所有
    2. get_queryset方法,配置queryset類屬性,提供視圖類相關的Models
    3. 在第二條基礎上,get_object方法,配置lookup_url_kwarg類屬性,提供視圖類相關的具體Model
    4. get_serializer方法,配置serializer_class類屬性,提供視圖類相關的序列化對象
    '''
    總結:
    	GenericAPIView就是在APIView基礎上額外提供了三個方法,三個類屬性,如果不配合視圖工具類,體現不出優勢
    	
    目的:
    	視圖中的增刪改查邏輯相似,但操作的資源不一致,操作資源就是操作 資源對象們、資源對象以及資源相關的序列化類,
    將這三者形成配置,那操作邏輯就一致,就可以進行封裝
    '''
    
  3. mixins視圖工具類們:五個類,六個方法

    '''
    要配合GenericAPIView類使用,將單查、群查、單增,單整體改,單局部改,單刪六個接口
    
    封裝成retrieve、list、create、update、partial_update、destroy六個方法
    
    原因:
    	六個方法的實現體,調用的方法就是GenericAPIView提供的,所以要配合GenericAPIView類使用
    '''
    
  4. generics工具視圖類們:九種組合

    1. 幫我們將不同個數不同種類的mixins與GenericAPIView進行組合
    2. 不同的組合幫我們實現好對應的get、post、put、patch、delete方法
    3. 需要我們自己配置三個類屬性即可: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設置映射關系
'''


免責聲明!

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



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