前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >测试开发进阶(二十九)

测试开发进阶(二十九)

作者头像
zx钟
发布2019-10-24 21:04:09
6610
发布2019-10-24 21:04:09
举报
文章被收录于专栏:测试游记

再次优化

查看 rest_framework.generics.CreateAPIView

rest_framework.generics.ListAPIView

可以看到很多重复的代码

rest_framework.generics.ListCreateAPIView

代码语言:javascript
复制
class ListCreateAPIView(mixins.ListModelMixin,                        mixins.CreateModelMixin,                        GenericAPIView):    """    Concrete view for listing a queryset or creating a model instance.    """    def get(self, request, *args, **kwargs):        return self.list(request, *args, **kwargs)    def post(self, request, *args, **kwargs):        return self.create(request, *args, **kwargs)

所以直接继承

代码语言:javascript
复制
from projects.models import Projectsfrom projects.serializer import ProjectModelSerializerfrom django_filters.rest_framework import DjangoFilterBackendfrom rest_framework import genericsclass ProjectsList(generics.ListCreateAPIView):    ordering_fields = ['name', 'leader']    queryset = Projects.objects.all()    serializer_class = ProjectModelSerializer    filter_backends = [DjangoFilterBackend]    filterset_fields = ['name', 'leader', 'tester']class ProjectDetail(generics.RetrieveUpdateDestroyAPIView):    queryset = Projects.objects.all()    serializer_class = ProjectModelSerializer

现有问题

  • 两个类视图,不能合并
  • 有相同的get方法
  • 两个类视图所对应的url地址不一致

再次优化

优化思路:使用动作来触发,而不是请求方法

代码语言:javascript
复制
from rest_framework import viewsets

viewsets不再支持 get/post/put/delete等请求方法,而只支持action动作

但是 ViewSet类中没有提供 get_object(), get_serializer等方法

继承 viewsets.GenericViewSet

将两个类合成一个类

修改url

代码语言:javascript
复制
from django.urls import pathfrom projects import viewsurlpatterns = [    path('project/', views.ProjectsViewSet.as_view({        'get': 'list',        'post': 'create'    }), name='projects_list'),    path('project/<int:pk>/', views.ProjectsViewSet.as_view({        'get': 'retrieve',        'put': 'update',        'delete': 'destroy'    }), name='project_detail')]
代码语言:javascript
复制
from projects.models import Projectsfrom rest_framework import viewsetsfrom projects.serializer import ProjectModelSerializerfrom django_filters.rest_framework import DjangoFilterBackendclass ProjectsViewSet(viewsets.ModelViewSet):    ordering_fields = ['name', 'leader']    queryset = Projects.objects.all()    serializer_class = ProjectModelSerializer    filter_backends = [DjangoFilterBackend]    filterset_fields = ['name', 'leader', 'tester']

视图

Django中

  • View

DRF中

  • APIView
  • GenericAPIView
  • mixins扩展类
  • CreateAPIView(合并拓展类)

视图集

action和请求方法的映射

  • ViewSet
  • GenericViewSet
  • CreateViewSet

路由

代码语言:javascript
复制
from rest_framework import routers
  1. 创建SimpleRouter路由对象
  2. 注册路由

第一个参数prefix为路由前缀,一般添加为应用名称即可 第二个参数viewset为视图集「不要加as_view」

  1. 将自动生成的路由添加到列表中
代码语言:javascript
复制
from django.urls import path, includefrom projects import viewsfrom rest_framework import routers# 1.创建SimpleRouter路由对象router = routers.SimpleRouter()# 2.注册路由# 第一个参数prefix为路由前缀,一般添加为应用名称即可# 第二个参数viewset为视图集「不要加as_view」router.register(r'projects',views.ProjectsViewSet)urlpatterns = [        # 将自动生成的路由添加到列表中    path('',include(router.urls))]

action

自定义action

代码语言:javascript
复制
from rest_framework.decorators import action
代码语言:javascript
复制
def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):    """    Mark a ViewSet method as a routable action.    Set the `detail` boolean to determine if this action should apply to    instance/detail requests or collection/list requests.    """    methods = ['get'] if (methods is None) else methods    methods = [method.lower() for method in methods]    assert detail is not None, (        "@action() missing required argument: 'detail'"    )    # name and suffix are mutually exclusive    if 'name' in kwargs and 'suffix' in kwargs:        raise TypeError("`name` and `suffix` are mutually exclusive arguments.")    def decorator(func):        func.mapping = MethodMapper(func, methods)        func.detail = detail        func.url_path = url_path if url_path else func.__name__        func.url_name = url_name if url_name else func.__name__.replace('_', '-')        func.kwargs = kwargs        # Set descriptive arguments for viewsets        if 'name' not in kwargs and 'suffix' not in kwargs:            func.kwargs['name'] = pretty_name(func.__name__)        func.kwargs['description'] = func.__doc__ or None        return func    return decorator

可以使用action装饰器来声明自定义的动作

默认情况下,实例方法名就是动作名

methods参数用于指定该动作支持的请求方法,默认为get

detail用于指定该动作要处理的是否为详情资源对象「url是否需要传递pk值」

url.py中添加

代码语言:javascript
复制
path('project/names/', views.ProjectsViewSet.as_view({    'get', 'names'}))

新增序列化器

代码语言:javascript
复制
class ProjectNameSerializer(serializers.ModelSerializer):    class Meta:        model = Projects        fields = ('id', 'name')

view中添加

代码语言:javascript
复制
@action(methods=['get'], detail=False)def names(self, request, *args, **kwargs):    queryset = self.get_queryset()    serializer = ProjectNameSerializer(instance=queryset, many=True)    return Response(serializer.data)

同理添加Interface

需要通过 projects/1/interfaces/来拿到 id=1interfaces信息

添加序列化器

代码语言:javascript
复制
class InterfacesNameSerializer(serializers.ModelSerializer):    class Meta:        model = Interfaces        fields = ('id', 'name', 'tester')class InterfacesByProjectIdSerializer(serializers.ModelSerializer):    interfaces_set = InterfacesNameSerializer(read_only=True, many=True)    class Meta:        model = Projects        fields = ('id', 'interfaces_sets')

添加自定义action

代码语言:javascript
复制
@action(detail=True)def interfaces(self, reques, *args, **kwargs):    instance = self.get_queryset()    serializer = InterfacesByProjectIdSerializer(instance=instance)    return Response(serializer.data)

查看路由

添加 url_pathurl_name

代码语言:javascript
复制
@action(methods=['get'], detail=False, url_path='nm', url_name='url_name')

urlpath url的路径名 urlname url的别名「应用名称-url_name」

测试

代码语言:javascript
复制
$ http :8000/projects/names/        
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试游记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 再次优化
    • 现有问题
      • 再次优化
        • 视图
          • 路由
            • action
              • 自定义action
              • 查看路由
            • 测试
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档