测试平台——项目模块模型类设计

news2024/11/16 6:32:50

这里写目录标题

  • 一、项目应用
    • 1、项目包含接口:
    • 2、创建子应用
    • 3、项目模块设计
      • a、模型类设计
      • b、序列化器类设计
      • c、视图类设计
    • 4、接口模块设计
      • a、模型类设计
      • b、序列化器类设计
      • c、视图类设计
    • 5、环境模块设计
    • 6、DRF中的通用过滤
      • 6.1、设置过滤器后端

一、项目应用

1、项目包含接口:

  • 项目管理接口
  • 接口管理接口
  • 环境管理接口

2、创建子应用

python manage.py startapp projects

3、项目模块设计

a、模型类设计

from django.db import models

# Create your models here.
class Project(models.Model):
    """项目表"""
    name = models.CharField(max_length=50, help_text='项目名称', verbose_name='项目名')
    leader = models.CharField(max_length=50, help_text='负责人', verbose_name='负责人', default='')
    create_time = models.DateTimeField(verbose_name='创建时间', help_text='创建时间', auto_now_add=True)

    class Meta:
        db_table = 'tb_project'
        verbose_name = '项目表'
        verbose_name_plural = verbose_name

    def _str__(self):
        return self.name

b、序列化器类设计

from rest_framework import serializers
from rest_framework.serializers import ModelSerializer

class ProjectSerializer(ModelSerializer):
    class Meta:
        model = Project
        fields = ['id', 'name', 'leader', 'create_time']

c、视图类设计

class ProjectViewSet(ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

获取项目的详情数据
需要展示字段:执行环境、执行场景、测试计划、接口数量、定时任务、执行记录

在这里插入图片描述
方法一:需要重写retrieve方法

class ProjectViewSet(ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

    # permission_classes = [IsAuthenticated]

    def retrieve(self, request, *args, **kwargs):
        response = super().retrieve(self, request, *args, **kwargs)
        obj = self.get_object()
        response.data['info'] = [
            {'name': '执行环境', 'value': TestEnv.objects.filter(project_id=obj.id).count()},
            {'name': '执行场景', 'value': TestScene.objects.filter(project_id=obj.id).count()},
            {'name': '测试计划', 'value': TestPlan.objects.filter(project_id=obj.id).count()},
            {'name': '接口数量', 'value': Interface.objects.filter(project_id=obj.id).count()},
            {'name': '定时任务', 'value': 0},  # todo 定时任务未开发
            {'name': '执行记录', 'value': Record.objects.filter(plan__project=obj).count()}
        ]
        return response

方法二:模型类中定义新的字段(重点)

模型类

class Project(models.Model):
    """项目表"""
    name = models.CharField(max_length=50, unique=True, help_text='项目名称', verbose_name='项目名')
    leader = models.CharField(max_length=50, help_text='负责人', verbose_name='负责人', default='')
    create_time = models.DateTimeField(verbose_name='创建时间', help_text='创建时间', auto_now_add=True)

    class Meta:
        db_table = 'tb_project'
        verbose_name = '项目表'
        verbose_name_plural = verbose_name

    def _str__(self):
        return self.name

    def info(self):
        return [
            {'name': '执行环境', 'value': self.test_envs.count()},
            {'name': '执行场景', 'value': self.test_scenes.count()},
            {'name': '测试计划', 'value': self.test_plans.count()},
            {'name': '接口数量', 'value': self.interfaces.count()},
            {'name': '定时任务', 'value': 0},       #todo 定时任务未开发
            {'name': '执行记录', 'value': Record.objects.filter(plan__project=self).count()}
        ]

序列化器设计

class ProjectSerializer(ModelSerializer):
    class Meta:
        model = Project
        fields = ['id', 'name', 'leader', 'create_time', 'info', 'bugs']

视图设计

class ProjectViewSet(ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

4、接口模块设计

a、模型类设计

class Interface(models.Model):
    """接口表"""
    CHOICES = [
        ('1', '项目接口'),
        ('2', '外部接口')]

    project = models.ForeignKey('Project',
                                on_delete=models.CASCADE,
                                help_text='项目id',
                                verbose_name='项目id',
                                related_name='interfaces')
    name = models.CharField(max_length=50, help_text='接口名称', verbose_name='接口名称')
    url = models.CharField(max_length=200, help_text='接口路径', verbose_name='接口路径')
    method = models.CharField(max_length=50, help_text='请求方法', verbose_name='请求方法')
    type = models.CharField(verbose_name='接口类型',
                            help_text='接口类型',
                            max_length=40,
                            choices=CHOICES,
                            default='1')

    # 扩展,接口的说明,接口字段的参数

    def __str__(self):
        return self.url

    class Meta:
        db_table = 'tb_interface'
        verbose_name = '接口表'
        verbose_name_plural = verbose_name

b、序列化器类设计

class NestTestStepSerializer(ModelSerializer):
    """嵌套测试步骤序列化器"""

    class Meta:
        model = TestStep
        fields = ['id', 'title']


class InterfaceSerializer(ModelSerializer):
    steps = NestTestStepSerializer(many=True, read_only=True, source='teststep_set')

    class Meta:
        model = Interface
        fields = '__all__'

    def validate(self, attrs):
        url = attrs.get('url')
        type_ = attrs.get('type')
        if type_ == '2':
            if not url.startswith('http'):
                raise serializers.ValidationError('外部接口的url需要完整的url,必须以http或者https开头')
        return attrs

获取接口的列表信息时:还需要将接口的下用例信息获取出来

c、视图类设计

5、环境模块设计

class TestEnv(models.Model):
    """测试坏境表"""
    name = models.CharField(max_length=150, help_text='环境名称', verbose_name='环境名称')
    project = models.ForeignKey(Project,
                                on_delete=models.CASCADE,
                                help_text='项目id',
                                verbose_name='项目id')
    global_variable = models.JSONField(help_text='全局变量',
                                       verbose_name='全局变量',
                                       default=dict,
                                       null=True)
    debug_global_variable = models.JSONField(help_text='debug模式全局变量',
                                             verbose_name="debug模式全局变量",
                                             default=dict,
                                             null=True)
    db = models.JSONField(help_text='数据库配置',
                          verbose_name='数据库配置',
                          default=list,
                          null=True,blank=True)
    host = models.CharField(help_text='base_url地址',
                            verbose_name='base_url地址',
                            max_length=100,
                            null=True,blank=True)
    headers = models.JSONField(help_text='请求头',
                               verbose_name='请求头',
                               default=dict,
                               null=True, blank=True)
    global_func = models.TextField(help_text='全局工具函数',
                                   verbose_name='全局工具函数',
                                   default=open('./utils/global_func.py', 'r',
                                                encoding='utf-8').read(),
                                   null=True,blank=True)

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'tb_testenv'
        verbose_name = '接口表'
        verbose_name_plural = verbose_name

6、DRF中的通用过滤

除了能够覆盖默认查询集之外,REST 框架还包括对通用过滤后端的支持,允许您轻松构建复杂的搜索和过滤器。

6.1、设置过滤器后端

可以使用设置全局设置默认过滤器后端DEFAULT_FILTER_BACKENDS。例如。

a、要使用DjangoFilterBackend,请先安装django-filter

pip install django-filter

注意djoango-filter仅支持:
● Python: 3.6,3.7,3.8
● Django: 2.2, 3.1,3.2
● DRF: 3.10+

b、注册

INSTALLED_APPS = [
    ...
    'django_filters',
	...
]

c、配置

REST_FRAMEWORK = {
	...
	...
    # 过滤
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}

d、使用
在后端类视图或者视图集中添加filterset_fields属性即可实现指定字段过滤,例如改写环境管理视图集
如下:

class EnvViewSet(ModelViewSet):
    queryset = TestEnv.objects.all()
    serializer_class = EnvSerializer
    filterset_fields = ['name','project']

不需要在复写get_queryset方法手动过滤,就可以通过url/test_envs/?project=1访问过滤数据了。
注意:当使用外键字段过滤时,如果级联模式是删除,则使用不存在的数据过滤会返回400响应。例如上面的
视图如果使用不存在的项目id过滤返回结果如下:

http://127.0.0.1:8000/test_envs?project=2

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/838590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

js省市区下拉框联动——前端笔记

问题: 我们常常要用到下拉框联动的功能,比如最常用的是选择地址的 省 市 区 的联动。思路: 先填充第一个下拉框,然后写一个第一个下拉框的change事件来加载第二个下拉框,再写第二个下拉框的change事件来加载第三个下…

面试总结-c++

1该吹牛逼吹牛逼。在自己能说出个所以然的情况下,该吹就吹,不吹没工作,吹了有希望。 比如 c组长,确有其事,但是挺唬人。说自己在北京定居也是侧面吹牛逼,证明自己的能力。还有媳妇在研究所。 2.对自己做过…

uniapp:图片验证码检验问题处理

图形验证码功能实现 uniapp:解决图形验证码问题及利用arraybuffer二进制转base64格式图片(后端传的图片数据形式:x00\x10JFIF\x00\x01\x02\x00…)_❆VE❆的博客-CSDN博客 UI稿: 需求:向后端请求验证码图片&…

Flask 是什么?Flask框架详解及实践指南

Flask 是一个轻量级的 Python Web 框架,它被广泛用于构建 Web 应用程序和 API。Flask 简单易用,具有灵活性和可扩展性,是许多开发者喜欢用其构建项目的原因。本文将介绍 Flask 是什么以及如何使用它来构建 Web 应用程序,同时提供一…

《Java-SE-第二十八章》之CAS

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限&…

Cocos Creator的 Cannot read property ‘applyForce‘ of undefined报错

序: 1、博主是看了这个教程操作的时候出的bug>游戏开发 | 17节课学会如何用Cocos Creator制作3D跑酷游戏 | P9 代码控制对象移动_哔哩哔哩_bilibili 2、其实问题不是出在代码上,但是发现物体就是不平移 3、node全栈的资料》node全栈框架 正文…

【文件操作:解锁高效读写与管理技巧】

本章重点 为什么使用文件 什么是文件 文件的打开和关闭 文件的顺序读写 文件的随机读写 文本文件和二进制文件 文件读取结束的判定 文件缓冲区 1. 为什么使用文件 C语言中的变量和数据通常只在程序运行时存在于内存中,一旦程序结束,这些数据就…

LeetCode933. 最近的请求次数

题干 写一个 RecentCounter 类来计算特定时间范围内最近的请求。 请你实现 RecentCounter 类: RecentCounter() 初始化计数器,请求数为 0 。int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回…

三、PWM呼吸灯

1. 什么是呼吸灯 如下图中的蓝色LED灯,不再是亮灭交替,而是慢慢亮慢慢灭,这就是呼吸灯 生活中常见 2. 怎样实现? 答:用PWM

Android中级——RemoteView

RemoteView RemoteView的应用NotificationWidgetPendingIntent RemoteViews内部机制模拟RemoteViews RemoteView的应用 Notification 如下开启一个系统的通知栏,点击后跳转到某网页 public class MainActivity extends AppCompatActivity {private static final …

项目一:基于stm32的阿里云智慧消防监控系统

若该文为原创文章,转载请注明原文出处。 Hi,大家好,我是忆枫,今天向大家介绍一个单片机项目。 一、简介 智慧消防监控系统,是用于检测火灾,温度,烟雾的监控系统。以 stm32单片机为核心外加 MQ…

一次redis缓存不均衡优化经验

背景 高并发接口,引入redis作为缓存之后,运行一段时间发现redis各个节点在高峰时段的访问量严重不均衡,有的节点访问量7000次/s,有的节点访问量500次/s 此种现象虽然暂时不影响系统使用,但是始终是个安全隐患&#x…

ARM进阶:内存屏障(DMB/DSB/ISB)的20个使用例子详解

在上一节内存屏障指令之DMB、DSB和ISB详解中,介绍了一下内存屏障的三个指令的作用并举了一些例子,对于内存屏障指令的使用时机,与处理器架构(比如Cortex-M和Cortex-A)和处理器的系统实现(同样的架构,有不同的实现,如ST…

大厂必面:你们系统qps多少,怎么部署的?假设每天有几千万请求,该如何部署?

前言 在40岁老架构师 尼恩的读者社区(50)中,很多小伙伴要拿高薪,这就要面大厂、面架构,拿高薪。 在高级开发面试、大厂面试、架构师的面试过程中,常常会遇到下面的问题: 你们系统qps多少?怎么部署的&…

第三章 图论 No.4最小生成树的简单应用

文章目录 裸题:1140. 最短网络裸题:1141. 局域网裸题:1142. 繁忙的都市裸题:1143. 联络员有些麻烦的裸题:1144. 连接格点 存在边权为负的情况下,无法求最小生成树 裸题:1140. 最短网络 1140. 最…

【三极管双稳态电路】2022-3-5

缘由multisim仿真问题-嵌入式-CSDN问答

《算法竞赛·快冲300题》每日一题:“ 盲文文字编码”

《算法竞赛快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 盲…

《cuda c编程权威指南》05 - cuda矩阵求和

目录 1. 使用一个二维网格和二维块的矩阵加法 1.1 关键代码 1.2 完整代码 1.3 运行时间 2. 使用一维网格和一维块的矩阵加法 2.1 关键代码 2.2 完整代码 2.3 运行时间 3. 使用二维网格和一维块的矩阵矩阵加法 3.1 关键代码 3.2 完整代码 3.3 运行时间 1. 使用一个二…

==和equals():比较对象等不等?

引言: 在编程中,我们常常需要判断两个对象是否相等。而在Java中,有两种常用的方法:使用""运算符和调用equals()方法。这两个方法有什么区别呢?它们又有哪些有趣的应用呢?让我们一起来探索一下吧&…

RTT学习笔记12-KConfig 语法学习

KConfig 语法学习 RTT 官方教程 https://www.rt-thread.org/document/site/#/development-tools/build-config-system/Kconfig 我自己写的IIC配置 menuconfig BSP_USING_I2C # I2C 菜单bool "Enable I2C BUS" # 提示I2C 菜单default n # 默认不使能I2C 菜单…