上一章:
七、Django DRF框架GenericAPIView--搜索&排序&分页&返回值_做测试的喵酱的博客-CSDN博客
下一章:
九、DRF生成API文档_做测试的喵酱的博客-CSDN博客
一、视图集ModelViewSet与ReadOnlyViesSet
ModelViewSet视图集 与 ReadOnlyViesSet视图集
1、ModelViewSet视图集:支持增删改查,如果需要对某个模型进行增删改查操作,才会选择ModelViewSet
2、ReadOnlyViesSet视图集:只支持读取操作,如果仅仅只对某个模型进行数据读取操作(取列表数据接口、获取详情数据接口),一般会选择ReadOnlyModelViewSet。
二、视图集ModelViewSet
ModelViewSet是一个最完整的视图集类。
1、提供了获取列表数据接口、获取详情数据接口、创建数据接口、更新数据接口、删除数据的接口(增删改查接口)
2、如果需要对某个模型进行增删改查操作,才会选择ModelViewSet
 3、如果仅仅只对某个模型进行数据读取操作(取列表数据接口、获取详情数据接口),一般会选择ReadOnlyModelViewSet
class ProjectViewSet(viewsets.ModelViewSet):
    """
    list:
    获取项目列表数据
    retrieve:
    获取项目详情数据
    update:
    更新项目信息
    names:
    获取项目名称
    """
    queryset = Projects.objects.all()
    serializer_class = ProjectModelSerializer
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['=name', '=leader', '=id']
    ordering_fields = ['id', 'name', 'leader']
    # 可以在类视图中指定分页引擎类,优先级高于全局
    pagination_class = PageNumberPagination 
2.0 类视图的设计原则
  a.类视图尽量要简单
  b.根据需求选择相应的父类视图
  c.如果DRF中的类视图有提供相应的逻辑,那么就直接使用父类提供的
  d.如果DRF中的类视图,绝大多数逻辑都能满足需求,可以重写父类实现
  e.如果DRF中的类视图完全不满足要求,那么就直接自定义即可 
2.1 自定义视图集方法action
场景:当视图集默认提供的方法,不能满足需求时,可以自定义action方法。
    @action(methods=['GET'], detail=False)
    def names(self, request, *args, **kwargs):
        # queryset = self.get_queryset()
        # queryset = self.filter_queryset(queryset)
        # names_list = []
        # for project in queryset:
        #     names_list.append({
        #         'id': project.id,
        #         'name': project.name
        #     })
        # serializer = self.get_serializer(queryset, many=True)
        #
        # # return Response(names_list, status=200)
        # return Response(serializer.data, status=200)
        return super().list(request, *args, **kwargs) 
2.1.1 函数定义
2.1.2 action装饰
@action(methods=['GET'], detail=False, url_path='xxx', url_name='yyyy') 
如果需要使用路由器机制自动生成路由条目,那么就必须得使用action装饰器
 1、methods(非必填)指定需要使用的请求方法,如果不指定,默认为GET
 2、detail(必填)指定是否为详情接口,是否需要传递当前模型的pk值
      如果需要传递当前模型的pk值,那么detail=True,否则detail=False
 3、url_path指定url路径,默认为action方法名称
 4、url_name指定url路由条目名称后缀,默认为action方法名称
127.0.0.1:8000/projects/names/
127.0.0.1:8000/projectsxxx/$[name='projects-yyy']
   @action(detail=True)
    def interfaces(self, request, *args, **kwargs):
        project = self.get_object()
        interfaces_qs = project.interfaces_set.all()
        interfaces_data = [{'id': interface.id, 'name': interface.name} for interface in interfaces_qs]
        return Response(interfaces_data, status=200) 
127.0.0.1:8000/projects/12/interfaces/
  

三、路由 routers
3.1 SimpleRouter路由
引入
from rest_framework import routers 
1、可以使用路由器对象,为视图集类自动生成路由条目
 2、路由器对象默认只为通用action(create、list、retrieve、update、destroy)生成路由条目,自定义的action不会生成路由条目
 3、创建SimpleRouter路由对象
  
router = routers.SimpleRouter() 
4、使用路由器对象调用register方法进行注册
router.register(r'projects', views.ProjectViewSet) 
- prefix指定路由前缀,如上r‘projects’
 - viewset指定视图集类,不可调用as_view,如上views.ProjectViewSet
 
5、设置路由条目
方式一:路由器对象.urls属性可获取生成的路由条目
urlpatterns = [
  
    # 路由器对象.urls属性可获取生成的路由条目
    path('', include(router.urls)),
] 
方式二:两个路由列表相加
# router.urls为列表
urlpatterns += router.urls
 
3.2 DefaultRouter路由
创建SimpleRouter路由对象
router = routers.SimpleRouter() 
创建DefaultRouter路由对象
router = routers.DefaultRouter() 
  DefaultRouter与SimpleRouter功能类似,仅有的区别为:DefaultRouter会自动生成一个根路由(显示获取数据的入口)
四、同一个视图集ModelViewSet中,对同一个模型类不同形式的输出
场景:
一个视图集ModelViewSet,下有多个action方法,比如获取list 、获取数据详情retrieve
这两个action获取的是同一个序列化器类。
当我要求获取数据列表与获取详情的内容 展示字段不同。
4.1 视图集ModelViewSet 采用多个序列化器类
场景:
一个视图集ModelViewSet,下有多个action方法,比如获取list 、获取数据详情retrieve
这两个action获取的是同一个序列化器类。
当我要求获取数据列表与获取详情的内容 展示字段不同时,需要采用多个序列化器类。
一个视图集ModelViewSet,如何使用多个action对应多个序列化器?
重写get_serializer_class 方法。
    def get_serializer_class(self):
        """
        a.可以重写父类的get_serializer_class方法,用于为不同的action提供不一样的序列化器类
        b.在视图集对象中可以使用action属性获取当前访问的action方法名称
        :return:
        """
        if self.action == 'names':
            return ProjectsNamesModelSerailizer
        else:
            # return self.serializer_class
            return super().get_serializer_class() 
4.2 重写action方法
场景:
一个视图集ModelViewSet,下有多个action方法,比如获取list 、获取数据详情retrieve
这两个action获取的是同一个序列化器类。
当我要求获取数据列表与获取详情的内容 展示字段不同时,重写action方法。
将多余的返回值干掉
    def retrieve(self, request, *args, **kwargs):
        response = super().retrieve(request, *args, **kwargs)
        response.data.pop('id')
        response.data.pop('create_time')
        return response 
                


















