接口测试平台核心以Httprunner为接口用例运行框架,要将用例的数据持久化到数据库中,方便读取修改与存储,则需要按照 yaml/json 的数据结构来设计数据库。
数据库模型关系图的总体结构
执行命令 django-admin startproject AutoTpsite
创建一个项目名为 AutoTpsite
的Django项目
再执行python manage.py startapp sqtp
命令创建一个名为 sqtp的应用
模型代码设计
其中,request,step和config参考HR对应部分的字段,由于其中会出现很多嵌套字段,所以1层的字段就用json数据类型来代替。
在models.py
下创建模型
配置config部分
class Config(models.Model):
name = models.CharField('测试用例名称',max_length=128)
base_url = models.CharField('IP/域名',max_length=256,null=True,blank=True) #可为空或者空白
variables = models.JSONField('变量',null=True)
parameters = models.JSONField('参数',null=True)
export = models.JSONField('用例返回值',null=True)
verify = models.BooleanField('https校验',default=False)
def __str__(self):
return self.name
# 以 测试用例名称 对外展示
通过 models.JSONField
可指定此字段为存储类型为JSON格式。null=True
表示此字段可以为空,这个NULL指的是SQL NULL,如果想存储为JsonNULL,则可以使用 Value('null')
来实现
用例Case部分
class Case(models.Model):
# 一对一关系指向配置config 关联约束选择 DO_NOTHING 不做删除,保留
config = models.OneToOneField(Config,on_delete=models.DO_NOTHING)
# 用例文件路径,用于后续数据的导出
file_path = models.CharField('用例文件路径',max_length=1000,default='demo_case.json')
def __str__(self):
return self.config.name
# 以 config名称(测试用例名称) 对外展示
测试用例与配置config的对应关系为 一对一 ,通过 models.OneToOneField
配置关联约束
测试步骤Step部分
class Step(models.Model):
# related_name 反向查询名称 同个模型中,两个字段关联同1个模型,必须指定related_name ,且名字不能相同
# 属于哪条测试用例,属于的用例被删除了,测试步骤也就没有存在的必要了 关联约束选择 CASCADE级联删除
belong_case = models.ForeignKey(Case,on_delete=models.CASCADE,related_name='teststeps')
# 引用的哪条测试用例,引用的用例被删除了,测试步骤可能还需要存在 关联约束选择 DO_NOTHING 不做删除,保留,或 SET_NULL 允许为null
linked_case = models.ForeignKey(Case,on_delete=models.SET_NULL,null=True,related_name='linked_steps')
name = models.CharField('测试步骤名称', max_length=128)
variables = models.JSONField('变量', null=True)
extract = models.JSONField('请求返回值', null=True)
validate = models.JSONField('校验项', null=True)
setup_hooks = models.JSONField('初始化', null=True)
teardown_hooks = models.JSONField('清除', null=True)
def __str__(self):
return self.name
# 以 测试步骤名称 对外展示
Httprunner测试框架中,测试步骤可以属于某条测试用例,一条测试用例中可能会存在多条测试用例;而测试步骤也能引用其他测试用例。
在数据存储的观点来看,测试步骤与测试用例之间的关系为 多对一 ,通过外键 ForeignKey 进行关联,但在模型的设计中,需要将这两种关联关系区分开来,所以需要有两个字段。两个字段关联同1个模型,这里需要通过related_name
反向查询名称进行区分,且名字不能相同
请求Request部分
class Request(models.Model):
# 一对一关系指向测试步骤Step 关联约束选择 CASCADE级联删除
step = models.OneToOneField(Step,on_delete=models.CASCADE,null=True)
# method可选字段,二维元组
method_choices = (
(0, 'GET'), # 参数1:保存在数据库中的值,参数2:对外显示的值
(1, 'POST'),
(2, 'PUT'),
(3, 'DELETE'),
)
method = models.SmallIntegerField('请求方法',choices=method_choices,default=0)
url = models.CharField('请求路径', default='/', max_length=1000)
params = models.JSONField('url参数', null=True)
headers = models.JSONField('请求头', null=True)
cookies = models.JSONField('Cookies', null=True)
data = models.JSONField('data参数', null=True)
json = models.JSONField('json参数', null=True)
def __str__(self):
return self.url
# 以 请求路径 对外展示
http请求方式通常有GET、POST、PUT、DELETE,像这种数据库存储字段的值有限定内容的时候,可以先创建一个二维元组,参数1表示保存在数据库中的值,参数2表示对外显示的值,通过choices
指定创建的二维元素。数据库中只需要存0、1、2、3这些数字即可,不需要设定为CharField
类型,设定为SmallIntegerField
即可,这种方式可以减少数据存储的压力。
正向查询与反向查询解析
在1对1,1对多,多对多关系中都存在正向查询和反向查询,模型查询其关联的项目叫做正向查询
如多对一关系中,正向查询是多方查询单方,因为外键是定义在多方,通过模型对象的外键 即modelObj.foreigner
进行查询则为正向查询;反向查询是单方查找多方,通过模型对象的外键模型的小写_set
即modelObj.foreigner_set
进行查询
在tests.py文件下进行测试
from django.test import TestCase
# Create your tests here.
from sqtp.models import Case,Config,Step,Request
class TestRelatedQuery(TestCase):
def setUp(self) -> None:
self.config1 = Config.objects.create(name='用例1',base_url='http://127.0.0.1:8080/')
self.config2 = Config.objects.create(name='用例2',base_url='http://127.0.0.1:8888/')
self.case1 = Case.objects.create(config=self.config1)
self.case2 = Case.objects.create(config=self.config2)
def test_steps_query(self):
step1 = Step.objects.create(belong_case=self.case1, name='步骤1') # 步骤1关联用例1
step1.linked_case = self.case2 # 步骤1引用用例1
step1.save()
step2 = Step.objects.create(belong_case=self.case2, name='步骤2') # 步骤2关联用例2
# 正向查询
print('===========正向查询===========')
print(step1.belong_case) #查看step1所属用例
print(step1.linked_case) # 查看step1引用的用例
print(step2.belong_case) #查看step2所属的用例
# 反向查询
print('===========反向查询===========')
# related_name代替 step_set
print(self.case1.teststeps.all()) # 查询用例1下面有哪些步骤
print(self.case2.linked_steps.all()) # 查询用例2被哪些步骤引用
输出结果
===========正向查询===========
用例1
用例2
用例2
===========反向查询===========
<QuerySet [<Step: 步骤1>]>
<QuerySet [<Step: 步骤1>]>
外键在 Step模型 中定义,与 Case模型 进行关联,而 Case模型 与 Config模型 一对一关联。
通过Step
查询关联的用例,则是正向查询
通过用例查询步骤,则是属于反向查询,正常情况下要通过模型小写_set
(即step_set)进行查询,但是在Step模型 中比较特殊,两个字段关联同1个模型,所以需要用 related_name 代替 step_set
Json字段操作解析
模型中大部分字段都是json类型(Django模型 JSONField类型)存储,以Request(请求信息)模型为例,操作增删改查
在tests.py文件下进行测试
新增
from django.test import TestCase
# Create your tests here.
from sqtp.models import Case, Config, Step, Request
from django.db.models import Value
class TestJsonField(TestCase):
def setUp(self) -> None:
print('====================新增数据======================')
req1 = Request.objects.create(method=1,url='/mgr/student/',data={"name":"小明","age":16,"address":"广东广州","school":{"PrimarySchool":"实验小学","SecondarySchool":"第一中学"}})
req2 = Request.objects.create(method=0,url='/api/teacher/',data={"name":"小王老师","courses":"英语","address":"广东深圳"})
req3 = Request.objects.create(method=3,url='/api/delete/',data={"id":105,"display_idx":1})
req = Request.objects.all()
print(req)
执行命令python manage.py test sqtp.tests.TestJsonField
进行测试
通过objects.create()
新增数据,通过Request.objects.all()
查询数据,输出结果
====================新增数据======================
<QuerySet [<Request: /mgr/student/>, <Request: /api/teacher/>, <Request: /api/delete/>]>
查询
Json条件查询
class TestJsonField(TestCase):
def setUp(self) -> None:
print('====================新增数据======================')
req1 = Request.objects.create(method=1,url='/mgr/student/',data={"name":"小明","age":16,"address":"广东广州","school":{"PrimarySchool":"实验小学","SecondarySchool":"第一中学"}})
req2 = Request.objects.create(method=0,url='/api/teacher/',data={"name":"小王老师","courses":"英语","address":"广东深圳"})
req3 = Request.objects.create(method=3,url='/api/delete/',data={"id":105,"display_idx":1})
req = Request.objects.all()
print(req)
def test_json_01(self):
print('====================查询数据======================')
req1 = Request.objects.all().first()
print(req1)
print(req1.data) # 查询data数据内容
print('====================json条件查询======================')
req2 = Request.objects.filter(data__age=16)
print(req2)
req3 = Request.objects.filter(data__school__PrimarySchool="实验小学")
print(req3)
通过Request.objects.all().first()
查询出第一条数据
若想要根据json里的内容筛选数据,可以根据字段名__参数名
(注意是双下划线)查询json字段里的内容,存在多层嵌套,依旧可以查询成功
输出结果
====================查询数据======================
/mgr/student/
{'name': '小明', 'age': 16, 'address': '广东广州', 'school': {'PrimarySchool': '实验小学', 'SecondarySchool': '第一中学'}}
====================json条件查询======================
<QuerySet [<Request: /mgr/student/>]>
<QuerySet [<Request: /mgr/student/>]>
字段条件查询
字段查询是指如何指定 SQL WHERE子句 的内容。它们用作 QuerySet 的 filter()、exclude() 和 get() 方法的关键字参数。 其基本格式是:field__lookuptype=value
(注意其中是双下划线),默认查找类型为exact(精确匹配)。
Django的数据库API支持20多种查询类型:
字段名 | 说明 |
---|---|
exact | 精确匹配 |
iexact | 不区分大小写的精确匹配 |
contains | 包含匹配 |
icontains | 不区分大小写的包含匹配 |
in | 在…之内的匹配 |
gt | 大于 |
gte | 大于等于 |
lt | 小于 |
lte | 小于等于 |
startswith | 从开头匹配 |
istartswith | 不区分大小写从开头匹配 |
endswith | 不区分大小写从结尾处匹配 |
range | 范围匹配 |
date | 日期匹配 |
year | 年份 |
iso_year | 以ISO 8601标准确定的年份 |
month | 月份 |
day | 日期 |
week | 第几周 |
week_day | 周几 |
iso_week_day | 以ISO 8601标准确定的星期几 |
quarter | 季度 |
time | 时间 |
hour | 小时 |
minute | 分钟 |
second | 秒 |
regex | 区分大小写的正则匹配 |
iregex | 不区分大小写的正则匹配 |
以上字段条件查询对非JSONField 类型的模型字段,同样适用
class TestJsonField(TestCase):
def setUp(self) -> None:
print('====================新增数据======================')
req1 = Request.objects.create(method=1,url='/mgr/student/',data={"name":"小明","age":16,"address":"广东广州","school":{"PrimarySchool":"实验小学","SecondarySchool":"第一中学"}})
req2 = Request.objects.create(method=0,url='/api/teacher/',data={"name":"小王老师","courses":"英语","address":"广东深圳"})
req3 = Request.objects.create(method=3,url='/api/delete/',data={"id":105,"display_idx":1})
def test_json_02(self):
print('====================字段条件查询======================')
req4 = Request.objects.filter(url__contains='mgr')
print(req4)
req5 = Request.objects.filter(method__in=[0,1,2])
print(req5)
输出结果
====================字段条件查询======================
<QuerySet [<Request: /mgr/student/>]>
<QuerySet [<Request: /mgr/student/>, <Request: /api/teacher/>]>
跨关系查询
Django提供了强大并且直观的方式解决跨越关联的查询,它在后台自动执行包含 JOIN 的 SQL语句。要跨越某个关联,只需使用关联的模型字段名称,并使用双下划线分隔,直至你想要的字段(可以链式跨越,无限跨度)
class TestOverRelations(TestCase):
def setUp(self) -> None:
# 创建用例
self.config1 = Config.objects.create(name='用例1', base_url='http://127.0.0.1:8080/')
self.config2 = Config.objects.create(name='用例2', base_url='http://127.0.0.1:8888/')
self.case1 = Case.objects.create(config=self.config1)
self.case2 = Case.objects.create(config=self.config2)
def test_step_request(self):
# 准备测试数据 步骤和请求
step1 = Step.objects.create(belong_case=self.case1,name='步骤1')
step2 = Step.objects.create(belong_case=self.case1,name='步骤2')
step3 = Step.objects.create(belong_case=self.case2,name='步骤3')
req1 = Request.objects.create(method=0,url='/api/teacher1/',data={"name":"小王老师","courses":"英语","address":"广东深圳"},step=step1)
req2 = Request.objects.create(method=1,url='/api/teacher2/',data={"name":"小王老师","courses":"英语","address":"广东深圳"},step=step2)
req3 = Request.objects.create(method=2,url='/api/teacher3/',data={"name":"小王老师","courses":"英语","address":"广东深圳"},step=step3)
print(req1.step.belong_case) # 链式语法 通过请求查询步骤再查询所属的用例(通过模型关联一步步查询
print(Request.objects.filter(step=step1))
# 跨关系查询
print(Request.objects.filter(step__belong_case__config__name='用例1')) # 查询 用例1 下的步骤
跨关系查询语法:字段__关联字段
跨关系查询是根据上级数据特征查找下级的结果
用例1
<QuerySet [<Request: /api/teacher1/>]>
<QuerySet [<Request: /api/teacher1/>, <Request: /api/teacher2/>]>
修改
from django.test import TestCase
# Create your tests here.
from sqtp.models import Case, Config, Step, Request
from django.db.models import Value
class TestJsonField(TestCase):
def setUp(self) -> None:
print('====================新增数据======================')
req = Request.objects.create(method=1,url='/mgr/student/',data={"name":"小明","age":16,"address":"广东广州","school":{"PrimarySchool":"实验小学","SecondarySchool":"第一中学"}})
def test_json_04(self):
print('====================查询数据======================')
req1 = Request.objects.all().first()
print(req1)
print(req1.data) # 查询data数据内容
print('====================修改整个字段内容======================')
req1.data={"name":"小王","age":16,"籍贯":"江西南昌"}
req1.save()
print(Request.objects.all().first().data) # 查看修改后的内容
print('====================修改字段中json局部内容======================')
req2 = Request.objects.all().first()
print(req2.data['name']) # 修改前
req2.data['name'] = '小红'
req2.save()
print(Request.objects.all().first().data['name']) # 修改后
输出结果
====================查询数据======================
/mgr/student/
{'name': '小明', 'age': 16, 'address': '广东广州', 'school': {'PrimarySchool': '实验小学', 'SecondarySchool': '第一中学'}}
====================修改整个字段内容======================
{'name': '小王', 'age': 16, '籍贯': '江西南昌'}
====================修改字段中json局部内容======================
小王
小红
修改data字段的内容,data字段就变为了{'name': '小王', 'age': 16, '籍贯': '江西南昌'}
;如果只需要修改json数据中的部分内容,只需要对字典中下标名称进行赋值即可,保存后json数据的内容就修改成功了
删除
from django.test import TestCase
# Create your tests here.
from sqtp.models import Case, Config, Step, Request
from django.db.models import Value
class TestJsonField(TestCase):
def setUp(self) -> None:
print('====================新增数据======================')
req = Request.objects.create(method=1,url='/mgr/student/',data={"name":"小明","age":16,"address":"广东广州","school":{"PrimarySchool":"实验小学","SecondarySchool":"第一中学"}})
def test_json_05(self):
print('====================查询数据======================')
req1 = Request.objects.all().first()
print(req1)
print(req1.data) # 查询data数据内容
print('====================删除字段局部的内容======================')
req1.data.pop('name')
req1.save()
print(Request.objects.all().first().data)
print('====================删除整个字段的内容======================')
req1.data = Value('null') # 设置成json的null
# req1.data = None # 设置成sql的null
req1.save()
print(Request.objects.all().first().data)
输出结果文章来源:https://www.toymoban.com/news/detail-433075.html
====================查询数据======================
/mgr/student/
{'name': '小明', 'age': 16, 'address': '广东广州', 'school': {'PrimarySchool': '实验小学', 'SecondarySchool': '第一中学'}}
====================删除字段局部的内容======================
{'age': 16, 'address': '广东广州', 'school': {'PrimarySchool': '实验小学', 'SecondarySchool': '第一中学'}}
====================删除整个字段的内容======================
None
删除字段json数据中的内容,则是通过pop()
函数完成;删除整个字段的数据,则是字段内容置为null
。文章来源地址https://www.toymoban.com/news/detail-433075.html
到了这里,关于Django JSONField类型操作解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!