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

测试开发进阶(三十六)

作者头像
zx钟
发布2019-11-14 14:51:28
3740
发布2019-11-14 14:51:28
举报
文章被收录于专栏:测试游记

项目模块

list优化

代码语言:javascript
复制
def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        datas = serializer.data
        datas = get_count_by_project(datas)
        return self.get_paginated_response(datas)

    serializer = self.get_serializer(queryset, many=True)
    datas = serializer.data
    datas = get_count_by_project(datas)
    return Response(datas)

这个 list其实就是拷贝了父类中的 list方法

使用

代码语言:javascript
复制
super().list(request, *args, **kwargs)

调用父类的 list方法

查看返回的 Response对象

所以优化为:

代码语言:javascript
复制
def list(self, request, *args, **kwargs):
    response = super().list(request, *args, **kwargs)
    response.data['results'] = get_count_by_project(response.data['results'])
    return response

重写getserializerclass

names中的 serializer使用 serializers.ProjectNameSerializer

为了让它可以直接使用 self.get_serializer方法,重写 get_serializer_class

源码
代码语言:javascript
复制
def get_serializer_class(self):
    """
    Return the class to use for the serializer.
    Defaults to using `self.serializer_class`.

    You may want to override this if you need to provide different
    serializations depending on the incoming request.

    (Eg. admins get full serialization, others get basic serialization)
    """
    assert self.serializer_class is not None, (
        "'%s' should either include a `serializer_class` attribute, "
        "or override the `get_serializer_class()` method."
        % self.__class__.__name__
    )

    return self.serializer_class
重写
代码语言:javascript
复制
def get_serializer_class(self):
    if self.action == 'names':
        return serializers.ProjectNameSerializer
    else:
        return self.serializer_class

报告模块

序列化器

代码语言:javascript
复制
from datetime import datetime
from rest_framework import serializers
from .models import Reports


class ReportsSerializer(serializers.ModelSerializer):
    """
    报告序列化器
    """

    class Meta:
        model = Reports
        exclude = ('update_time', 'is_delete')
        extra_kwargs = {
            'html': {
                'write_only': True
            },
            'create_time': {
                'read_only': True
            }
        }

    def create(self, validated_data):
        report_name = validated_data['name']
        validated_data['name'] = f"{report_name}_{datetime.strftime(datetime.now(), '%Y%m%d%H%M%S')}"
        report = Reports.objects.create(**validated_data)
        return report

从数据库中可以看出其中 html是一串字符串,它需要转换成html格式才可以正常展示,所以在接口返回的内容中不应该包含它,设置它为只写模式 write_only

create函数进行重定义

下面是数据库中显示的内容

代码语言:javascript
复制
name = models.CharField('报告名称', max_length=200, unique=True, help_text='报告名称')

查看 models文件可以看到 name字段是唯一的「 unique=True」所以我们在添加的时候需要携带上当前的时间信息

视图

定义一个类 ReportsViewSet还是继承 ModelViewSet

其他和之前的类似

其中要注意的是一个 download接口

代码语言:javascript
复制
import re
import os
from datetime import datetime

from django.conf import settings
from django.http import StreamingHttpResponse
from rest_framework.viewsets import ModelViewSet
from rest_framework import permissions
from rest_framework.decorators import action

from reports.utils import format_output, get_file_contents
from .models import Reports
from .serializers import ReportsSerializer


class ReportsViewSet(ModelViewSet):
    """
    list:
    返回测试报告(多个)列表数据

    create:
    创建测试报告

    retrieve:
    返回测试报告(单个)详情数据

    update:
    更新(全)测试报告

    partial_update:
    更新(部分)测试报告

    destroy:
    删除测试报告

    """
    queryset = Reports.objects.filter(is_delete=False)
    serializer_class = ReportsSerializer
    permission_classes = (permissions.IsAuthenticated,)
    ordering_fields = ('id', 'name')

    def perform_destroy(self, instance):
        instance.is_delete = True
        instance.save()

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        response.data['results'] = format_output(response.data['results'])
        return response

    @action(detail=True)
    def download(self, request, pk=None):
        instance = self.get_object()
        html = instance.html
        name = instance.name
        mtch = re.match(r'(.*_)\d+', name)
        if mtch:
            mtch = mtch.group(1) + datetime.strftime(datetime.now(), '%Y%m%d%H%M%S') + '.html'
        report_dir = os.path.join(settings.BASE_DIR, 'reports')
        report_path = os.path.join(report_dir, mtch)
        with open(report_path, 'w') as f:
            f.write(html)
        response = StreamingHttpResponse(get_file_contents(report_path))
        response['Content-Type'] = "application/octet-stream"
        response['Content-Disposition'] = "attachment; filename*=UTF-8''{}".format(name)
        return response

每次下载之后我们都会在本地存放一次,然后我们需要以数据流的方式返回html报告

代码语言:javascript
复制
response = StreamingHttpResponse(get_file_contents(report_path))
代码语言:javascript
复制
def get_file_contents(filename, chunk_size=512):
    with open(filename,encoding='utf8') as f:
        while True:
            c = f.read(chunk_size)
            if c:
                yield c
            else:
                break

这里用到了分段的方式,每512字节返回一次,直到全部返回完毕

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目模块
    • list优化
      • 重写getserializerclass
        • 源码
        • 重写
    • 报告模块
      • 序列化器
        • 视图
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档