这里写目录标题
- 一、项目应用
- 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_namedef _str__(self):return self.name
b、序列化器类设计
from rest_framework import serializers
from rest_framework.serializers import ModelSerializerclass ProjectSerializer(ModelSerializer):class Meta:model = Projectfields = ['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_namedef _str__(self):return self.namedef 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 = Projectfields = ['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.urlclass Meta:db_table = 'tb_interface'verbose_name = '接口表'verbose_name_plural = verbose_name
b、序列化器类设计
class NestTestStepSerializer(ModelSerializer):"""嵌套测试步骤序列化器"""class Meta:model = TestStepfields = ['id', 'title']class InterfaceSerializer(ModelSerializer):steps = NestTestStepSerializer(many=True, read_only=True, source='teststep_set')class Meta:model = Interfacefields = '__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.nameclass 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 = EnvSerializerfilterset_fields = ['name','project']
不需要在复写get_queryset方法手动过滤,就可以通过url/test_envs/?project=1访问过滤数据了。
注意:当使用外键字段过滤时,如果级联模式是删除,则使用不存在的数据过滤会返回400响应。例如上面的
视图如果使用不存在的项目id过滤返回结果如下:
http://127.0.0.1:8000/test_envs?project=2