ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

GenericAPIView, 视图工具类, 工具视图类, 视图集

2020-04-15 22:07:55  阅读:250  来源: 互联网

标签:GenericAPIView ... get self request 视图 kwargs 工具 serializer


目录

GenericAPIView类---泛型工具视图类

  • GenericAPIView类继承了APIView类
  • APIView类: 1. 通过重写as_view方法禁用了csrf校验, 2. 通过重写dispatch方法, 二次封装request, 进行drf三大认证, 以及二次封装response
  • GenericAPIView类定义了类属性: queryset, serializer_class, lookup_field, lookup_url_kwarg
  • GenericAPIView类定义了类方法: get_queryset, get_object, get_serializer, get_serializer_class
'''
# ...\Lib\site-packages\rest_framework\generics.py
class GenericAPIView(views.APIView):
    queryset = None
    serializer_class = None
    
    # 通过lookup_field对应的字段以及lookup_url_kwarg对应的字段值过滤出单个数据对象
    lookup_field = 'pk'  
    lookup_url_kwarg = None
    ...
    def get_queryset(self):
        ...
        queryset = self.queryset
        ...
        return queryset
        
     def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())
        
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        ...
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)
        ...
        return obj
        
    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)
        
    def get_serializer_class(self):
        ...
        return self.serializer_class
        

# ...\d_proj\api\urls.py
...
urlpatterns = [
    url(r'^v2/cars/$', views.CarGenericAPIView.as_view()),
    url(r'^v2/cars/(?P<xxx>\w+)/$', views.CarGenericAPIView.as_view()),
]
        
        
# ...\d_proj\api\views.py
...
class CarGenericAPIView(generics.GenericAPIView):
	print(type(models.Car.objects))  # <class 'django.db.models.manager.Manager'>
    print(type(models.Car.objects.all()))  # <class 'django.db.models.query.QuerySet'>
    print(type(models.Car.objects.filter()))  # <class 'django.db.models.query.QuerySet'>
    
    queryset = models.Car.objects.filter(is_delete=False).all()  
    serializer_class = serializers.CarModelSerializer
    lookup_url_kwarg = 'xxx'
    lookup_field = 'name'

    # # 群查
    # def get(self, request, *args, **kwargs):
    #     car_queryset = self.get_queryset()
    #     car_ser = self.get_serializer(instance=car_queryset, many=True)
    #     return Response(data={
    #         'code': 0,
    #         'res': car_ser.data,
    #     }, status=200)
	
    # 单查
    def get(self, request, *args, **kwargs):
        car_obj = self.get_object()
        car_ser = self.get_serializer(instance=car_obj, many=False)
        return Response(data={
            'code': 0,
            'res': car_ser.data,
        }, status=200)
'''

视图工具类

'''
# ...\Lib\site-packages\rest_framework\mixins.py
...
class CreateModelMixin:  # 单增
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        ...
        return Response(serializer.data, ...)

    def perform_create(self, serializer):
        serializer.save()
    ...


class ListModelMixin:  # 群查
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        ...
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class RetrieveModelMixin:  # 单查
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class UpdateModelMixin:  # 单改
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        ...
        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)


class DestroyModelMixin:  # 单删
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()
'''

工具视图类

'''
# ...\Lib\site-packages\rest_framework\generics.py
from rest_framework import mixins
...


class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
        
        
...
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                            mixins.UpdateModelMixin,
                            GenericAPIView):
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

'''

视图集

ViewSetMixin类---视图集工具类

  • ViewSetMixin类不继承任何类

  • 定义了as_view方法和view函数, 可以通过给该方法传入字典形式的参数, 实现自定义请求方式与请求处理函数的映射关系

GenericViewSet(ViewSetMixin, generics.GenericAPIView)---泛型视图集: 处理与数据库资源密切相关的请求

ViewSet(ViewSetMixin, views.APIView): 处理与数据库资源不是密切相关的请求, 例如: 登录, 短信验证码

'''
# ...\Lib\site-packages\rest_framework\viewsets.py
...
class ViewSetMixin:
    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        ...
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            self.action_map = actions

            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)
            ...
            return self.dispatch(request, *args, **kwargs)
        ...
        view.cls = cls
        view.initkwargs = initkwargs
        view.actions = actions
        return csrf_exempt(view)
    ...


class ViewSet(ViewSetMixin, views.APIView):
    pass


class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass


class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    pass


class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    pass
'''

实际开发中使用视图集时需要优化的点

  1. 重写destroy方法, 使删除操作变成将is_delete字段值修改为True
  2. 重写create方法完成单增群增, 使单增群增共用一个接口
  3. 添加群该所有字段接口, 群改部分字段接口, 群删接口
'''
# ...\d_proj\api\views.py
class CarModelViewSet(ModelViewSet):
    queryset = models.Car.objects.filter(is_delete=False).all()
    serializer_class = serializers.CarModelSerializer
    
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.is_delete = True
        instance.save()
        return Response(data={'code': 0, 'res': '删除成功'}, status=200)
	
    def create(self, request, *args, **kwargs):
        if isinstance(request.data, list):
            car_ser = self.serializer_class(data=request.data, many=True)
            car_ser.is_valid(raise_exception=True)
            instance = car_ser.save()
            re_car_ser = self.serializer_class(instance=instance, many=True)
            return Response(data={'code': 0, 'res': re_car_ser.data})
        return super().create(request, *args, **kwargs)
        
    def multiple_update(self, request, *args, **kwargs):
        return Response(data={'code': 0, 'res': '群改所有字段'}, status=200)

    def multiple_partial_update(self, request, *args, **kwargs):
        return Response(data={'code': 0, 'res': '群改部分字段'}, status=200)

    def multiple_destroy(self, request, *args, **kwargs):
        return Response(data={'code': 0, 'res': '群删'}, status=200)	

# ...\d_proj\api\urls.py
...
urlpatterns = [
    url(r'^v7/cars/$', views.CarModelViewSet.as_view({
        'get': 'list',
        'post': 'create',
        'put': 'multiple_update',
        'patch': 'multiple_partial_update',
        'delete': 'multiple_destroy',
    })),
    url(r'^v7/cars/(?P<pk>\d+)/$', views.CarModelViewSet.as_view({
        'get': 'retrieve',
        'put': 'update',
        'patch': 'partial_update',
        'delete': 'destroy',
    })),
]
'''

SimpleRouter简化...\d_proj\api\urls.py中的代码

'''
# ...\d_proj\api\urls.py
...
from .my_routers import MySimpleRouter

urlpatterns = [
    ...,
]
router = MySimpleRouter()
router.register('v7/cars', views.CarModelViewSet, basename='car')
urlpatterns.extend(router.urls)


# ...\d_proj\api\my_routers.py
from rest_framework.routers import SimpleRouter
from rest_framework.routers import Route


class MySimpleRouter(SimpleRouter):
    routes = [
        Route(
            url=r'^{prefix}{trailing_slash}$',
            mapping={
                'get': 'list',
                'post': 'create',
                'put': 'many_update',
                'patch': 'many_partial_update',
                'delete': 'many_destroy',
            },
            name='{basename}-list',
            detail=False,
            initkwargs={'suffix': 'List'}
        ),
        Route(
            url=r'^{prefix}/{lookup}{trailing_slash}$',
            mapping={
                'get': 'retrieve',
                'put': 'update',
                'patch': 'partial_update',
                'delete': 'destroy'
            },
            name='{basename}-detail',
            detail=True,
            initkwargs={'suffix': 'Instance'}
        ),
    ]
    

# ...\Lib\site-packages\rest_framework\routers.py
class SimpleRouter(BaseRouter):

    routes = [
        # List route.
        Route(
            url=r'^{prefix}{trailing_slash}$',
            mapping={
                'get': 'list',
                'post': 'create'
            },
            name='{basename}-list',
            detail=False,
            ...
        ),
        # Dynamically generated list routes. Generated using
        # @action(detail=False) decorator on methods of the viewset.
        DynamicRoute(
            url=r'^{prefix}/{url_path}{trailing_slash}$',
            name='{basename}-{url_name}',
            detail=False,
            ...
        ),
        ...,
    ]
    
    ...
    def get_default_basename(self, viewset):
        queryset = getattr(viewset, 'queryset', None)
        ...
        return queryset.model._meta.object_name.lower()
'''

标签:GenericAPIView,...,get,self,request,视图,kwargs,工具,serializer
来源: https://www.cnblogs.com/-406454833/p/12708782.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有