专栏首页测试游记测试开发进阶(二十九)

测试开发进阶(二十九)

再次优化

查看 rest_framework.generics.CreateAPIView

rest_framework.generics.ListAPIView

可以看到很多重复的代码

rest_framework.generics.ListCreateAPIView

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)

所以直接继承

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地址不一致

再次优化

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

from rest_framework import viewsets

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

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

继承 viewsets.GenericViewSet

将两个类合成一个类

修改url

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')]
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

路由

from rest_framework import routers
  1. 创建SimpleRouter路由对象
  2. 注册路由

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

  1. 将自动生成的路由添加到列表中
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

from rest_framework.decorators import action
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中添加

path('project/names/', views.ProjectsViewSet.as_view({    'get', 'names'}))

新增序列化器

class ProjectNameSerializer(serializers.ModelSerializer):    class Meta:        model = Projects        fields = ('id', 'name')

view中添加

@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信息

添加序列化器

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

@action(detail=True)def interfaces(self, reques, *args, **kwargs):    instance = self.get_queryset()    serializer = InterfacesByProjectIdSerializer(instance=instance)    return Response(serializer.data)

查看路由

添加 url_pathurl_name

@action(methods=['get'], detail=False, url_path='nm', url_name='url_name')

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

测试

$ http :8000/projects/names/        

本文分享自微信公众号 - 测试游记(zx94_11),作者:zx钟

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 测试开发进阶(十七)

    当 isNotFlag是 false的时候不显示,当 isNotFlag是 true的时候显示

    zx钟
  • Python设计模式-状态模式

    切换状态的时候会使用self.__class__将它动态切换到状态对应的对象,这个稍后再看。

    zx钟
  • scrapy结合selenium进行动态加载页面内容爬取

    使用requests进行数据获取的时候一般使用的是respond.text来获取网页源码,然后通过正则表达式提取出需要的内容。

    zx钟
  • 一分钟学会在JavaWeb项目中配置数据源

    剽悍一小兔
  • resteasy经验谈

    resteasy 是java体系中比较成熟的rest框架,也是jax-rs规范的实现之一,dubbox的REST服务框架,就是采用的resteasy实现,近日在...

    菩提树下的杨过
  • R语言实现GWAS数据文件格式转化

    全基因组关联分析(GWAS)大家都不陌生,今天我们给大家介绍下各种格式之间转化在R语言是怎么实现的。首先我们来看下GWAS都有哪些数据格式:

    一粒沙
  • 使用Prometheus监控MySQL性能指标

    这里使用--web.listen-address=":9200"修改默认启动端口,防止跟上文中启动的服务器监控冲突。

    JAVA日知录
  • udp传输大文件及打洞

    如果用UDP传输文件之类的东西,必须自己在上面再封装一层可靠的传输协议。可以参考reliable-udp这个规范(搜索一下RELIABLE UDP PROTOC...

    战神伽罗
  • 碎片化 | 第四阶段-36-struts-spring结合jdbc实现删除功能-视频

    如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/z05669dznu6.html ---- 结合jdbc实现删除功能(...

    码神联盟
  • Linux rsync命令使用指南

    rsync 命令是一个远程数据同步工具,可通过 LAN/WAN 快速同步多台主机间的文件。rsync 使用所谓的 “rsync算法” 来使本地和远程两个主机之间...

    smartsi

扫码关注云+社区

领取腾讯云代金券