三、【数据建模篇】:用 Django Models 构建测试平台核心数据
【数据建模篇】:用 Django Models 构建测试平台核心数据
- 前言
- 我们要设计哪些核心数据?
- 准备工作:创建 Django App
- 开始设计数据模型 (Models)
- 1. 通用基础模型 (可选但推荐)
- 2. 项目模型 (Project)
- 3. 模块模型 (Module)
- 4. 测试用例模型 (TestCase)
- 生成和应用数据库迁移
- 在 Django Admin 中查看和管理数据 (可选的快速验证)
- 总结
前言
- 在上一篇,我们成功搭建了 Django 和 Vue3 的开发环境,就像给我们的“建筑工地”通了水电一样。今天,我们要开始真正的“建筑设计”了——为我们的测试平台设计数据模型。
- 什么是数据模型?简单来说,数据模型就是我们测试平台需要存储和管理的信息的蓝图。比如,一个测试平台肯定要有“项目”、“测试用例”、“测试报告”这些东西,数据模型就是用来精确定义这些“东西”包含哪些信息(比如项目名称、用例步骤、报告结果等),以及它们之间是如何关联的。
- 在 Django 中,我们使用 Models 来定义数据模型。你只需要用 Python 代码来描述你的数据结构,Django 会自动帮你处理与数据库交互的复杂细节(比如创建数据库表)。
我们要设计哪些核心数据?
一个基础的测试平台,通常会包含以下核心数据:
- 项目 (Project):管理不同的测试项目。
- 模块 (Module):项目下的功能模块,用于组织测试用例。
- 测试用例 (TestCase):具体的测试点,包含一系列操作步骤。
- 测试步骤 (TestStep):测试用例中的单个操作,如访问URL、点击按钮、校验结果等(为了简化入门,我们初期可以将步骤内置于用例中,后续可拆分)。
- 测试配置 (EnvironmentConfig / TestConfig):用于存储不同测试环境的配置信息,如URL、账户等 (初期简化,可放在项目中或后续添加)。
- 测试执行记录 (TestRun / ExecutionRecord):记录每一次测试任务的执行情况。
- 测试报告 (TestReport):汇总展示某次测试执行的结果。
为了让小白更容易上手,我们先从最核心的 项目 (Project)、模块 (Module) 和 测试用例 (TestCase) 开始设计,并逐步完善。
准备工作:创建 Django App
在 Django 中,项目通常由多个 App 组成,每个 App 负责一部分独立的功能。我们将创建一个名为 api
的 App 来存放我们测试平台后端的核心逻辑,包括数据模型。
-
激活 Python 虚拟环境:
- 打开Terminal:
- Windows:
venv\Scripts\activate
- macOS/Linux:
source venv/bin/activate
- Windows:
- 打开Terminal:
-
创建 Django 项目:
虽然我们之前安装了 Django,但还没有正式创建一个 Django 项目。一个 Django 项目是配置和多个应用的集合。
在test-platform
目录下 (确保(venv)
已激活),执行:django-admin startproject backend .
注意命令最后的那个点
.
,它表示在当前目录 (test-platform
) 下创建 Django 项目文件,而不是再新建一个同名子目录。执行后,你的
test-platform
目录结构如下图所示:这里的
backend
文件夹是 Django 项目的配置目录,settings.py
是项目配置文件,而manage.py
是Django 项目管理脚本工具,我们将频繁使用它。 -
创建 Django App:
现在,使用manage.py
来创建我们的api
应用。确保你在test-platform
根目录下。python manage.py startapp api
执行后,
test-platform
目录下会新增一个api
文件夹:
我们将在models.py
这里定义数据模型。 -
注册 App:
创建了 App 之后,还需要告诉 Django 项目它的存在。打开test-platform/backend/settings.py
文件,找到INSTALLED_APPS
列表,在列表末尾添加我们的api
应用:
# test-platform/backend/settings.pyINSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','rest_framework', # 我们之前安装了DRF,在这里也注册上'api', # 添加我们新建的 app ]
记得保存文件。
开始设计数据模型 (Models)
现在,打开 test-platform/api/models.py
文件。这个文件初始只有一些注释。我们将在这里用 Python 类来定义我们的数据模型。
1. 通用基础模型 (可选但推荐)
为了代码复用和统一管理创建时间、更新时间等通用字段,我们可以先定义一个基础模型。
# test-platform/api/models.py
from django.db import modelsclass BaseModel(models.Model):"""公共模型,可添加创建时间/更新时间/逻辑删除等通用字段"""name = models.CharField(max_length=100, unique=True, verbose_name="名称")description = models.TextField(null=True, blank=True, verbose_name="描述")create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")class Meta:abstract = True # 设置为抽象基类,不会在数据库中创建表ordering = ['-create_time'] # 默认按创建时间倒序def __str__(self):return self.name
models.Model
: 所有 Django 模型都继承自它。name = models.CharField(...)
: 定义一个字符类型字段,max_length
是最大长度,unique=True
表示名称不能重复,verbose_name
是在 Django admin 后台显示的友好名称。description = models.TextField(...)
: 定义一个文本类型字段,null=True
表示数据库中可以为空,blank=True
表示在表单中可以不填。create_time = models.DateTimeField(auto_now_add=True, ...)
: 日期时间字段,auto_now_add=True
表示在对象第一次创建时自动设置为当前时间。update_time = models.DateTimeField(auto_now=True, ...)
: 日期时间字段,auto_now=True
表示在对象每次保存时自动更新为当前时间。class Meta
: 用于定义模型的元数据。abstract = True
: 表示BaseModel
是一个抽象基类。它本身不会被创建成数据库表,而是用来被其他模型继承,从而共享这些通用字段。ordering = ['-create_time']
: 指定查询此模型的对象时,默认按创建时间降序排列 (最新的在前面)。
__str__(self)
: 定义当打印模型实例时,返回的内容。这里我们返回其名称。
2. 项目模型 (Project)
一个测试项目是我们组织测试的顶层单位。
# test-platform/api/models.py
# (继续在同一个文件中添加,BaseModel定义之后)class Project(BaseModel): # 继承自我们定义的 BaseModel"""项目表"""# name 和 description 字段已从 BaseModel 继承# create_time 和 update_time 字段已从 BaseModel 继承# 可以添加项目特有的字段,例如:#负责人owner = models.CharField(max_length=50, null=True, blank=True, verbose_name="负责人")#项目状态:0-规划中,1-进行中,2-已完成,3-搁置status = models.PositiveSmallIntegerField(default=1, verbose_name="项目状态", help_text="0:规划中, 1:进行中, 2:已完成, 3:搁置")class Meta:verbose_name = "项目" # 单数形式的友好名称verbose_name_plural = "项目列表" # 复数形式的友好名称ordering = ['-create_time'] # 也可以在这里覆盖或添加排序规则# __str__ 方法已从 BaseModel 继承
我们让 Project
模型继承了 BaseModel
,所以它自动拥有了 name
, description
, create_time
, update_time
字段。我们又添加了 owner
和 status
两个项目特有的字段。
3. 模块模型 (Module)
模块通常属于某个项目,用于对测试用例进行分类。
# test-platform/api/models.py
# (继续在同一个文件中添加)class Module(BaseModel):"""模块表"""# name 和 description 字段已从 BaseModel 继承# create_time 和 update_time 字段已从 BaseModel 继承project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name="所属项目", related_name="modules")# 'Project':关联到 Project 模型。# on_delete=models.CASCADE:级联删除。当其所属的 Project 被删除时,这个 Module 也会被自动删除。# verbose_name:友好名称。# related_name="modules":这允许我们从一个 Project 实例通过 `project_instance.modules.all()` 来获取其下所有的 Module 实例。class Meta:verbose_name = "模块"verbose_name_plural = "模块列表"# 同一个项目下的模块名不能重复unique_together = ('project', 'name') # project 和 name 组合起来必须唯一# __str__ 方法已从 BaseModel 继承,可以考虑重写以包含项目信息def __str__(self):return f"{self.project.name} - {self.name}"
这里最重要的是 project = models.ForeignKey(Project, ...)
,它定义了一个外键关系。这意味着一个模块必须属于一个项目。
4. 测试用例模型 (TestCase)
测试用例是测试的核心,它属于某个模块。
# test-platform/api/models.py
# (继续在同一个文件中添加)class TestCase(BaseModel):"""测试用例表"""# name 和 description 字段已从 BaseModel 继承# create_time 和 update_time 字段已从 BaseModel 继承module = models.ForeignKey(Module, on_delete=models.CASCADE, verbose_name="所属模块", related_name="testcases")# 用例级别: P0, P1, P2, P3priority_choices = [('P0', 'P0 - 最高'),('P1', 'P1 - 高'),('P2', 'P2 - 中'),('P3', 'P3 - 低'),]priority = models.CharField(max_length=2, choices=priority_choices, default='P1', verbose_name="优先级")# 前置条件precondition = models.TextField(null=True, blank=True, verbose_name="前置条件")# 测试步骤 (初期简化,直接存在用例中,可以用JSON格式或特定文本格式)# 更好的做法是单独创建一个 TestStep 模型,并与 TestCase 建立一对多关系steps_text = models.TextField(verbose_name="测试步骤 (文本描述)")# 预期结果expected_result = models.TextField(verbose_name="预期结果")# 用例类型:例如 功能测试,接口测试,UI测试 (初期可以简单点,后续扩展)case_type_choices = [('functional', '功能测试'),('api', '接口测试'),('ui', 'UI测试'),]case_type = models.CharField(max_length=20, choices=case_type_choices, default='functional', verbose_name="用例类型")# 维护人maintainer = models.CharField(max_length=50, null=True, blank=True, verbose_name="维护人")class Meta:verbose_name = "测试用例"verbose_name_plural = "测试用例列表"# 同一个模块下的用例名不能重复unique_together = ('module', 'name')# __str__ 方法已从 BaseModel 继承,可以考虑重写def __str__(self):return f"{self.module.project.name} - {self.module.name} - {self.name}"
priority = models.CharField(..., choices=priority_choices, ...)
:choices
参数允许你定义一个下拉选择列表。steps_text
: 我们暂时用一个大的文本字段来存储测试步骤,这对于入门比较简单。在更复杂的系统中,你可能会创建一个单独的TestStep
模型,并让一个TestCase
关联多个TestStep
。
生成和应用数据库迁移
模型定义好了,但数据库还不知道这些。我们需要告诉 Django 根据我们的模型定义来创建或修改数据库表结构。这个过程叫做数据库迁移 (Migrations)。
-
生成迁移文件:
在终端中 (确保在test-platform
目录下,并且(venv)
已激活),运行:python manage.py makemigrations api
你会看到以下输出:
如果你的模型定义没有语法错误,Django 会检查
api/models.py
文件的改动,并在api/migrations/
目录下生成一个新的迁移文件,0001_initial.py
。这个文件描述了如何创建Project
,Module
,TestCase
表。 -
应用迁移到数据库:
迁移文件生成后,运行以下命令将这些更改应用到数据库(Django 默认使用 SQLite 文件数据库,它会在你项目根目录下自动创建一个db.sqlite3
文件):python manage.py migrate
你会看到以下输出,表示你的数据库表已经根据模型成功创建了!
验证数据库表 (可选,但推荐)
我们可以使用 SQLite 的浏览器工具(比如 DB Browser for SQLite)打开项目根目录下的 db.sqlite3
文件,查看是否生成了表,以及它们的列结构是否符合定义。
在 Django Admin 中查看和管理数据 (可选的快速验证)
Django 自带一个强大的后台管理界面 (Django Admin),我们可以用它来快速查看和添加数据,验证模型是否工作正常。
-
创建超级用户:
你需要一个管理员账号来登录 Django Admin。在终端运行:
python manage.py createsuperuser
按照提示输入用户名、邮箱(可以随便填一个格式正确的)、密码。
-
注册模型到 Admin:
打开test-platform/api/admin.py
文件,将我们的模型注册进去:
# test-platform/api/admin.py from django.contrib import admin from .models import Project, Module, TestCase # 导入你的模型# 注册模型到 admin 站点 admin.site.register(Project) admin.site.register(Module) admin.site.register(TestCase)
-
启动开发服务器:
python manage.py runserver
默认情况下,服务器会运行在
http://127.0.0.1:8000/
。
访问http://127.0.0.1:8000/
,安装成功如下图所示:
-
访问 Admin 界面:
在浏览器中打开http://127.0.0.1:8000/admin/
。
使用你刚才创建的超级用户账号登录。
登录后,你能看到 “API” 部分,下面列出了 “模块列表”, “测试用例列表”, “项目列表”。你可以点击它们,尝试添加一些测试数据。
通过 Django Admin 添加几条数据,验证下模型之间的关系是否按预期工作。比如:
-
创建一个项目 “电商平台测试”。
-
在 “电商平台测试” 项目下创建一个模块 “用户登录模块”。
-
在 “用户登录模块” 下创建一个测试用例 “TC001_正确用户名密码登录”,再输入测试步骤和预期结果。
总结
你已经成功为测试平台设计了核心的数据模型,并学会了以下内容:
- ✅ 在 Django 中创建 App。
- ✅ 使用 Python 类定义 Django Models (Project, Module, TestCase)。
- ✅ 理解了字段类型、外键关系 (
ForeignKey
)、元数据 (class Meta
) 的基本用法。 - ✅ 生成并应用了数据库迁移 (
makemigrations
,migrate
)。 - ✅ 通过 Django Admin 快速验证了模型。
在下一篇文章中,我们将基于这些模型,开始使用 Django REST Framework (DRF) 来创建后端 API 接口,让前端能够通过网络来读取和操作这些数据。
相关文章:

三、【数据建模篇】:用 Django Models 构建测试平台核心数据
【数据建模篇】:用 Django Models 构建测试平台核心数据 前言我们要设计哪些核心数据?准备工作:创建 Django App开始设计数据模型 (Models)1. 通用基础模型 (可选但推荐)2. 项目模型 (Project)3. 模块模型 (Module)4. 测试用例模型 (TestCase…...
【JAVA】比较器Comparator与自然排序(28)
JAVA 核心知识点详细解释 Java中比较器Comparator的概念和使用方法 概念 Comparator 是 Java 中的一个函数式接口,位于 java.util 包下。它用于定义对象之间的比较规则,允许我们根据自定义的逻辑对对象进行排序。与对象的自然排序(实现 Comparable 接口)不同,Comparat…...

shp2pgsql 导入 Shp 到 PostGIS 空间数据库
前言 ❝ shp2pgsql是PostGIS自带的命令行工具,用于将Shapefile文件声称SQL脚本导入到PostGIS空间数据库。 1. 安装 PostGIS 通过Application Stack Builder或者下载单独的PostGIS包进行安装。而shp2pgsql则是与PostGIS工具集成在一起,无需单独下载。该命…...

word设置如“第xx页 共xx页”格式的页码
问题1: 为word文档设置如“第xx页 共xx页”格式的页码。 解决方法: 1、鼠标双击页脚位置进入页脚编辑模式; 2、在页脚处输入“第 页 共 页”内容并居中; 3、将光标放在“第 页”之间并插入“Page”,执行操作“…...

DL00912-基于自监督深度聚类的高光谱目标检测含数据集
在科研的道路上,数据的获取与分析无疑是成功的关键。对于从事高光谱数据研究的你,我们为您带来了一款革命性的工具——基于自监督深度聚类的高光谱目标检测系统。 完整代码数据集见文末 这款系统通过最先进的自监督学习技术,结合深度聚类算…...
PostgreSQL架构
目录 一、PostgreSQL核心特性与优势 1.PostgreSQL简介 2.PostgreSQL的核心特点 (1)开源与自由 (2)高度符合SQL标准 (3)丰富的数据类型 (4)事务与并发控制 (5&…...
文章记单词 | 第111篇(六级)
一,单词释义 damage /ˈdmɪdʒ/ v./n. 损害;损坏;损失harbour /ˈhɑːbə(r)/ n. 港口;港湾 v. 庇护;窝藏(美式拼写:harbor)gasp /ɡsp/ v. 喘气;喘息 n. 喘息&#x…...
在Java中,将Object对象转换为具体实体类对象
在Java中,将Object对象转换为具体实体类对象可以通过以下几种方法实现: 1.使用instanceof关键字进行类型检查和转换: 首先,使用instanceof关键字检查Object对象是否为目标实体类的类型。 如果是,则进行强制类型…...

Runtipi - 开源个人家庭服务器管理工具
项目功能:家庭服务器管理 ▎项目介绍: 一个开源的个人家庭服务器管理工具,旨在简化在单一服务器上管理和运行多个服务的过程。 它基于 Docker 构建,提供了一个简单的 Web 界面,用户可以通过该界面轻松添加和管理服务…...
Vue3和React中插件化设计思想
Vue 3 和 React 都广泛支持插件化设计思想,但因为它们的架构和理念不同,插件化的实现方式也不尽相同。以下分别详细讲解这两者中如何实现插件化: 🟩 一、Vue 3 中的插件化实现 Vue 3 继承了 Vue 2 的插件机制,同时增强…...
基于ResNet的医学影像辅助诊断系统
源码下载地址: https://download.csdn.net/download/shangjg03/90873910 1. 简介 医学影像辅助诊断系统是利用计算机视觉和深度学习技术,帮助医生分析医学影像(如X光、CT、MRI等)并提供诊断建议的系统。本教程将开发一个基于ResNet的胸部X光肺炎检测系统。 2. 准备工作...

HJ106 字符逆序【牛客网】
文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 HJ106 字符逆序 一、题目描述 二、测试用例 三、解题思路 基本思路: 考虑到可能会有多个空格,使用使用 getline 函数直接读取一行。 如果可以直接打印的…...

力扣HOT100之二叉树: 236. 二叉树的最近公共祖先
果然,这道题二刷还是不会做,回去看卡尔视频了。结合灵神的题解,我对这道题有了一些新的理解。 首先这道题还是用递归来做,由于我们需要计算两个节点的最近公共祖先,一定是从下往上来遍历,只有先判断左右子树…...

腾讯音乐一面
1、自我介绍项目(省略) 2、为什么存储要从TiDB迁移到Mysql? TiDB 迁移至 MySQL 核心原因总结: 成本优化 TiDB 需多节点集群(PD/TiKV/TiDB Server),硬件、运维及学习成本高。中小业务(…...
【PhysUnits】4.4 零类型(Z0)及其算术运算(zero.rs)
一、源码 该代码定义了一个类型系统中的零类型Z0,并为其实现了基本的算术运算(加法、减法、乘法、除法)。这是一个典型的类型级编程示例,使用Rust的类型系统在编译期进行数学运算。 //! 零类型(Z0)及其算术运算实现 //! //! 本…...

Pluto实验报告——基于2ASK的简易的通信系统
一、实验目的 1. 熟悉并掌握PLUTO SDR 主动学习模块的使用; 2.通过matlab 编码与adalm pluto 相配合达成一个简易的通信系统,并能 够传输一些较为简单的信息。 二、实验原理 2ASK 调制原理: 振幅键控是指利用载波的振幅变化来传递数字基带信…...
Python排序函数全面指南:从基础到高级
文章目录 Python排序函数全面指南:从基础到高级1. 两种主要排序方式2. 基本参数详解2.1 key参数:自定义排序规则2.2 reverse参数:控制排序方向 3. 高级排序技巧3.1 多级排序3.2 稳定排序 4. 性能考虑5. 特殊排序场景5.1 对自定义对象排序5.2 …...

深入了解redis的哈希槽的知识
目录 1、哈希算法分类 1.1、简单哈希算法 1.2、一致性哈希算法 1、原理: 2、解决问题 3、数据倾斜问题 4、虚拟节点 2. 哈希槽 2.1、介绍 2. 2、作用 1、数据分片(Sharding) 2、高可用性(HA) 3…...

农业机械化、电气化和自动化知网英文普刊:1天录用,2周见刊发表!
CSP科学出版社,旨在通过为研究人员提供最佳环境来发表、参考、阅读和引用他们的作品,从而为科学界服务。现已与科检易学术达成出版战略合作,现在联合共同出版高质量学术水平的期刊,为方便广大科研学者投稿方便,现已经建…...
java将rtsp转成flv在浏览器播放
1、添加maven依赖 <dependency> <groupId>io.github.javpower</groupId> <artifactId>rtsp-converter-flv-spring-boot-starter</artifactId> <version>1.5.9.2</version> </dependency> 2、在配置application.ymlÿ…...

Docker-Compose使用自定义网桥后在OpenWrt系统中容器无法访问网络解决方案
Docker-Compose使用自定义bridge网桥后在OpenWrt系统中容器无法访问网络解决方案 示例compose描述文件如下,注意最后网络配置: # docker-compose --env-file .env.yoko.prod.local up -d services:...postgres:image: kuluseky/postgres-zhparser-post…...

界面组件DevExpress WPF中文教程:Grid - 行和卡片
DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…...

Qt enabled + geometry 属性(2)
文章目录 enabled属性可用与禁用的概念API接口代码演示 阐述说明1. 先简单描述下要如何演示出上面两个接口的效果(思路)2. 事先规范按钮对象的命名3. 定义两个按钮对象的槽函数 动图演示效果4. widget.cpp geometry属性预备知识API接口上下左右移动 ta…...

Llamaindex自学笔记(完)
Llamaindex框架主要做RAG,工作流用LangGraph做 换源: -i https://pypi.mirrors.ustc.edu.cn/simple/环境搭建: conda create -n llamaindex python3.12 conda activate llamaindexpip install llama-index pip install llama-cloud-servic…...
安全生态与职业跃迁
18. 网络安全产业生态 18.1 全球安全产业链解析 核心参与者角色 安全厂商: 终端安全:CrowdStrike、SentinelOne(EDR/XDR) 网络防御:Palo Alto Networks、Fortinet(NGFW/SASE) 云安全&#…...

飞书知识问答深度测评:企业AI应用落地的“范本级”产品
前言 当 AI 逐渐从技术前沿走向日常办公,我们最常听到的一个词是“效率提升”。但真正能做到降本增效、让企业员工切实受益的 AI 产品,仍属少数。尤其是在组织内部知识管理这一块,大多数企业仍停留在“搜索靠关键词、记录靠记忆、协作靠问人…...

draw.io的基础与进阶使用指南
前言 一、Draw.io 简介 Draw.io 是一款功能强大的绘图工具,支持在线使用和本地安装。它提供了丰富的模板和形状元素,能够绘制流程图、UML 图、甘特图、网络图等多种图形。Draw.io 的文件格式支持可编辑的矢量图和位图,方便后续修改 draw.io的…...
clang的介绍与使用
一、Clang 简介 Clang 是一个开源的 C/C/Objective-C 编译器前端,基于 LLVM(Low Level Virtual Machine) 项目开发。它被设计为替代传统 GCC 的现代化编译器,具有以下特点: 高性能:编译速度快,…...
GD32 IIC(I2C)通信(使用示例为SD2068)
一、前言 最近需要用到GD32的I2C通信,虽然是第一次做I2C通信,但是GD32完整的标准库有现存的I2C通信示例,虽然示例是EEPROM的通信,但是调用的函数应该是大差不差,所以上手比较简单,这里简单记录一下笔记&…...

Sanitizers
一、简介 sanitizers 是谷歌提供的一套开源工具,能够发现堆栈读写溢出、内存泄漏、线程数据竞争和死锁等问题。包括: AddressSanitizers (Asan):检测地址相关问题,如use-after-free,heap-buffer-overflow, stack_buffer_overflow,use_after_…...