Django 模型的继承
- 项目管理
- 模型关联关系
- 模块的包管理
- 模型的继承
项目管理
到目前为止,都是属于httprunner中的用例部分,针对核心功能进行的开发工作,要把平台做成一个用户可以使用的程度还需要些额外的功能,比如项目管理,用户管理等。
首先考虑需要增加的数据模型,项目管理需要项目,模块,和测试环境等相关数据,同时原有模型需要增加一些额外的通用字段,如增加时间,更新时间等。
模型关联关系
首先确立模型的关联关系
用例和项目之间的关联可以直接通过config,因为config是套件和用例的扩展,相当于用例和套件本身。
模块的包管理
在我们使用 python manage.py startapp xxx
命令创建新的应用时,Django会自动帮我们建立一个应用的基本文件组织结构,其中就包括一个 models.py
文件。通常,我们把当前应用的模型都编写在这个文件里,但是如果你的模型很多,那么将单独的 models.py
文件分割成一些独立的文件是个更好的做法。
首先,我们需要在应用中新建一个叫做 models
的包,包下自动创建了一个__init__.py
文件,该文件是用于确立包的身份,建同名的目的是为了其他引用原model.py
文件的模块中代码不需发生更改。
新增一个hr3.py
文件,将 models.py
文件中的代码复制到hr3.py
文件中,然后删除 models.py
文件
最后在 __init__.py
文件中导入所有的模型。
from .hr3 import Step,Case,Config,Request
要显式明确地导入每一个模型,而不要使用 from .models import *
的方式,这样不会混淆命名空间,让代码更可读,更容易被分析工具使用。
最终的模型结构
其中hr3.py
存放所有核心数据模型,mgr.py
存放所有项目管理相关(项目和环境数据)模型
mgr.py
# 存放所有项目管理相关模型
from django.db import models
# 定义项目 类
class Project(models.Model):
Pro_Status = (
('developing','开发中'),
('operating','维护中'),
('stable','稳定运行中'),
)
name = models.CharField(max_length=32,unique=True,verbose_name='项目名称')
status = models.CharField(max_length=32,choices=Pro_Status,default='stable',verbose_name='项目状态')
version = models.CharField(max_length=32,default='V1.0',verbose_name='版本')
def __str__(self):
return self.name # 以 项目名称 对外展示
# 模型元类
class Meta:
db_table = 'Project' # 如果不设置,默认的名称是 app名_模型名
ordering = ['id'] # 根据id排序(默认为顺序排序)
verbose_name = '项目表' # 表的对外显示名称
# 定义 测试环境 类
class Enviroment(models.Model):
# 服务器类型选项
service_type = (
(0,'web服务器'),
(1,'数据库服务器'),
(2,'文件存储服务器'),
)
# 服务器操作系统类型选项
service_os = (
(0, 'Windows'),
(1, 'CentOS'),
(2, 'Ubuntu'),
(3, 'Debian'),
)
# 服务器状态类型选项
service_status = (
(0, '未激活'),
(1, '使用中'),
(2, '已过期'),
)
project = models.ForeignKey(Project,on_delete=models.CASCADE,verbose_name='所属项目')
# django-ORM框架提供 GenericIPAddressField 专门存储ip类型信息,对入参ip格式会有校验
ip = models.GenericIPAddressField(default='127.0.0.1',verbose_name='IP地址')
# PositiveSmallIntegerField 正整数类型
port = models.PositiveSmallIntegerField(default=80,verbose_name='端口号')
category = models.SmallIntegerField(choices=service_type,default=0,verbose_name='服务器类型')
os = models.SmallIntegerField(choices=service_os,default=1,verbose_name='服务器操作系统')
status = models.SmallIntegerField(choices=service_status,default=0,verbose_name='服务器状态')
def __str__(self):
return self.ip+self.port
# 模型元类
class Meta:
db_table = 'Enviroment' # 如果不设置,默认的名称是 app名_模型名
ordering = ['id'] # 根据id排序(默认为顺序排序)
verbose_name = '测试环境表' # 表的对外显示名称
模型的继承
一般在实际项目中,数据模型除了业务字段以外,还需要有一些通用字段,如创建时间,更新时间,创建者,更新者等,这些字段如果在每个模型都定义的话,冗余度很高,而且维护起来不方便。
此时,我们可以用一个抽象模型类来存放这些字段,然后其他模型继承该抽象模型类即可。
在 models
包下创建了一个base.py
文件,定义一个抽象模型 CommonInfo
# 公共模型
from django.db import models
class CommonInfo(models.Model):
# 公共字段部分: 创建时间、更新时间、描述
create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
# auto_now_add 第一次创建数据时自动添加当前时间
update_time = models.DateTimeField(auto_now=True,verbose_name='更新时间')
# auto_now 每次更新数据时自动添加当前时间
desc = models.TextField(null=True,blank=True,verbose_name='描述')
def __str__(self):
# 判断当前数据对象是否有name属性,如果有,返回name,如果没有,返回描述
if hasattr(self,'name'): # hasattr 是Python中是反射的一种用法
return self.name
else:
return self.desc
class Meta:
abstract =True # 定义抽象表,不会创建数据库表
ordering = ['id'] # 根据id排序(默认为顺序排序)
由于在元类中定义了abstract = True
,抽象模型在同步数据库的时候并不会创建表,子类只会继承其字段和方法
另外元类除了abstract = True
不会继承,其他都会继承,若想把子类也设置为抽象模型,必须显示在元类中设置abstract = True
。
以mgr.py
中的模型为例,子类继承抽象父类:
mgr.py
# 存放所有项目管理相关模型
from django.db import models
from .base import CommonInfo
# 定义项目 类
class Project(CommonInfo):
Pro_Status = (
('developing','开发中'),
('operating','维护中'),
('stable','稳定运行中'),
)
name = models.CharField(max_length=32,unique=True,verbose_name='项目名称')
status = models.CharField(max_length=32,choices=Pro_Status,default='stable',verbose_name='项目状态')
version = models.CharField(max_length=32,default='V1.0',verbose_name='版本')
# 模型元类
class Meta(CommonInfo.Meta): # 元类也需要显示继承父类的元类才会生效
db_table = 'Project' # 如果不设置,默认的名称是 app名_模型名
verbose_name = '项目表' # 表的对外显示名称
# 定义 测试环境 类
class Enviroment(CommonInfo):
# 服务器类型选项
service_type = (
(0,'web服务器'),
(1,'数据库服务器'),
(2,'文件存储服务器'),
)
# 服务器操作系统类型选项
service_os = (
(0, 'Windows'),
(1, 'CentOS'),
(2, 'Ubuntu'),
(3, 'Debian'),
)
# 服务器状态类型选项
service_status = (
(0, '未激活'),
(1, '使用中'),
(2, '已过期'),
)
project = models.ForeignKey(Project,on_delete=models.CASCADE,verbose_name='所属项目')
# django-ORM框架提供 GenericIPAddressField 专门存储ip类型信息,对入参ip格式会有校验
ip = models.GenericIPAddressField(default='127.0.0.1',verbose_name='IP地址')
# PositiveSmallIntegerField 正整数类型
port = models.PositiveSmallIntegerField(default=80,verbose_name='端口号')
category = models.SmallIntegerField(choices=service_type,default=0,verbose_name='服务器类型')
os = models.SmallIntegerField(choices=service_os,default=1,verbose_name='服务器操作系统')
status = models.SmallIntegerField(choices=service_status,default=0,verbose_name='服务器状态')
def __str__(self):
return self.ip+self.port
# 模型元类
class Meta(CommonInfo.Meta):
db_table = 'Enviroment' # 如果不设置,默认的名称是 app名_模型名
ordering = ['-id'] # 根据id倒序排序
verbose_name = '测试环境表' # 表的对外显示名称
Project
类和Enviroment
类都需要继承CommonInfo
抽象类,且元类Meta
也需要继承CommonInfo中的Meta元类
,但如果有相同的字段,会被覆盖,比如Enviroment
类中排序ordering
是根据 id 倒序排序
类似的,对hr3.py
文件也可进行抽象类的继承
在 models
包下的 __init__.py
文件中导入所有的模型
from .hr3 import Step,Case,Config,Request
from .mgr import Enviroment,Project
将修改同步至数据库
python manage.py makemigrations
python manage.py migrate