自动化测试平台开发(七):接口测试 - DRF编写后端接口实现增、删、改、查
本篇讲解如果用djangorestframwork编写后端接口,事件数据表增删改查。这里只记录接口信息表的后端接口请求实现。
后端接口实现
一、自定义、封装
- 自定义Response,统一接口返回数据格式,便于前端请求数据解析。
- 自定义Pagination,定制分页,接口、用例数据量会比较大,查询最好分页查询
- 封装DRF ModelViewSet,应用自定义Response、自定义Pagination、django filters、登录认证等
- rest_framework_bulk 封装实现批量处理
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:base.py 6 @time:2021/08/24 7 @email:tao.xu2008@outlook.com 8 @description: 9 """ 10 from collections import OrderedDict 11 import six 12 from django.db.models import Count, Sum 13 from rest_framework.response import Response 14 from rest_framework.serializers import Serializer 15 from rest_framework.pagination import PageNumberPagination 16 from rest_framework.viewsets import ModelViewSet, GenericViewSet 17 from rest_framework_bulk import BulkModelViewSet 18 from rest_framework import filters 19 from django_filters.rest_framework import DjangoFilterBackend 20 from rest_framework.permissions import IsAuthenticated 21 from apps.api_test import logger 22 23 24 class JsonResponse(Response): 25 """ 26 An HttpResponse that allows its data to be rendered into 27 arbitrary media types. 28 """ 29 30 def __init__(self, data=None, code=2, msg='ok', success='true', 31 status=None, 32 template_name=None, headers=None, 33 exception=False, content_type=None): 34 """ 35 Alters the init arguments slightly. 36 For example, drop 'template_name', and instead use 'data'. 37 Setting 'renderer' and 'media_type' will typically be deferred, 38 For example being set automatically by the `APIView`. 39 """ 40 super(Response, self).__init__(None, status=status) 41 if isinstance(data, Serializer): 42 msg = ( 43 'You passed a Serializer instance as data, but ' 44 'probably meant to pass serialized `.data` or ' 45 '`.error`. representation.' 46 ) 47 raise AssertionError(msg) 48 self.data = {"code": code, "msg": msg, "success": success, "data": data} 49 self.template_name = template_name 50 self.exception = exception 51 self.content_type = content_type 52 53 if headers: 54 for name, value in six.iteritems(headers): 55 self[name] = value 56 57 58 # 定制化分页 59 class Pagination(PageNumberPagination): 60 def get_paginated_response(self, data): 61 return Response(OrderedDict([ 62 ('count', self.page.paginator.count), 63 ('page', self.page.number), 64 ('list', data) 65 ])) 66 67 page_size = 20 68 page_query_param = 'page' # 页码的名称 69 page_size_query_param = 'page_size' # 每页多少条 70 max_page_size = 10000 71 72 73 class TotalCountModelMixin(GenericViewSet): 74 """Total count a queryset.""" 75 def list(self, request, *args, **kwargs): 76 queryset = self.filter_queryset(self.get_queryset()) 77 return JsonResponse(data={'total': queryset.count()}, status=200) 78 79 80 class GroupCountModelMixin(GenericViewSet): 81 """Count a queryset by group.""" 82 filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] 83 default_group_by_field = 'id' # string, field 84 default_time_unit = '' # string, type(group_by_field)=DateTimeField --> year | month | day 85 time_unit_str = { 86 'year': '%%Y', 87 'month': '%%Y-%%m', 88 'week': '%%x-%%v', 89 'day': '%%Y-%%m-%%d', 90 } 91 92 def list(self, request, *args, **kwargs): 93 """ 94 分组查询 95 :param request: 96 group_by_field: 分组字段 97 time_unit: 若按时间分组,可设置时间单位 year | month | day 98 :param args: 99 :param kwargs: 100 :return: 101 """ 102 group_by_field = self.default_group_by_field 103 time_unit = self.default_time_unit 104 if 'group_by_field' in request.query_params: 105 request.query_params._mutable = True 106 group_by_field = request.query_params.get('group_by_field') 107 request.query_params.__delitem__('group_by_field') 108 request.query_params._mutable = False 109 110 if 'time_unit' in request.query_params: 111 request.query_params._mutable = True 112 time_unit = request.query_params.get('time_unit') 113 request.query_params.__delitem__('time_unit') 114 request.query_params._mutable = False 115 116 extra_select = { 117 group_by_field: "DATE_FORMAT({}, '{}')".format(group_by_field, self.time_unit_str[time_unit]) 118 } if time_unit else {} 119 queryset = self.filter_queryset(self.get_queryset().extra(select=extra_select).values(group_by_field)).\ 120 order_by(group_by_field).annotate(count=Count("id")).values(group_by_field, "count") 121 return JsonResponse(data=list(queryset.all()), status=200) 122 123 124 class ApiTestBaseViewSet(BulkModelViewSet): 125 # 登录认证 126 # permission_classes = [IsAuthenticated, ] 127 filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter] 128 pagination_class = Pagination # 分页 129 130 # 创建数据 131 def create(self, request, *args, **kwargs): 132 response = super().create(request, *args, **kwargs) 133 return JsonResponse(response.data, status=response.status_code) 134 135 # 检索数据 136 def retrieve(self, request, *args, **kwargs): 137 response = super().retrieve(request, *args, **kwargs) 138 return JsonResponse(response.data, status=response.status_code) 139 140 # 更新数据 141 def update(self, request, *args, **kwargs): 142 kwargs['partial'] = True # 强制修改为 局部更新数据 143 response = super().update(request, *args, **kwargs) 144 return JsonResponse(response.data, status=response.status_code) 145 146 # 局部更新数据 147 def partial_update(self, request, *args, **kwargs): 148 response = super().partial_update(request, *args, **kwargs) 149 return JsonResponse(response.data, status=response.status_code) 150 151 # 批量 更新数据 152 def bulk_update(self, request, *args, **kwargs): 153 response = super().bulk_update(request, *args, **kwargs) 154 return JsonResponse(response.data, status=response.status_code) 155 156 # 批量 局部更新数据 157 def partial_bulk_update(self, request, *args, **kwargs): 158 response = super().partial_bulk_update(request, *args, **kwargs) 159 return JsonResponse(response.data, status=response.status_code) 160 161 # 删除数据 162 def destroy(self, request, *args, **kwargs): 163 response = super().destroy(request, *args, **kwargs) 164 return JsonResponse(response.data, status=200) 165 166 # 批量 删除数据执行条件 167 def allow_bulk_destroy(self, qs, filtered): 168 print(qs.count()) 169 print(filtered.count()) 170 return (qs is not filtered) and self.request.query_params and qs.count() > filtered.count() 171 172 # 批量 删除数据 173 def bulk_destroy(self, request, *args, **kwargs): 174 response = super().bulk_destroy(request, *args, **kwargs) 175 if response.status_code == 400: 176 return JsonResponse(None, msg="筛选参错误/空,禁止全表删除!", code=500500, status=200) 177 return JsonResponse(response.data, status=200) 178 179 # 查询数据 180 def list(self, request, *args, **kwargs): 181 response = super().list(request, *args, **kwargs) 182 return JsonResponse(response.data, status=response.status_code) 183 184 185 if __name__ == '__main__': 186 pass
二、为每个表定义一个或多个序列化器,serializers
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:serializers.py 6 @time:2021/08/23 7 @email:tao.xu2008@outlook.com 8 @description: 9 """ 10 from django.contrib.auth.models import User 11 from rest_framework import serializers 12 from rest_framework_bulk import BulkSerializerMixin, BulkListSerializer 13 from rest_framework.authtoken.models import Token 14 15 from apps.api_test.models import Department, Project, ProjectDynamic, ProjectMember, \ 16 AppSetting, GlobalEnv, GlobalConst, GlobalHeader, GlobalResponseValidate, \ 17 ApiGroup, ApiInfo, ApiUpdateHistory, YApiEvent, GlobalLabel, \ 18 TestSuite, TestCase, TestStep, TestReport, TestTask, TestEnvMonitor 19 20 21 class TokenSerializer(serializers.ModelSerializer): 22 """ 23 用户信息序列化 24 """ 25 first_name = serializers.CharField(source="user.first_name") 26 last_name = serializers.CharField(source="user.last_name") 27 phone = serializers.CharField(source="user.user.phone") 28 email = serializers.CharField(source="user.email") 29 date_joined = serializers.CharField(source="user.date_joined") 30 31 class Meta: 32 model = Token 33 # fields = '__all__' 34 fields = ('first_name', 'last_name', 'phone', 'email', 'key', 'date_joined') 35 36 37 class UserSerializer(serializers.ModelSerializer): 38 39 class Meta: 40 model = User 41 fields = ('id', 'username', 'first_name', 'last_name', 'email') 42 43 44 class DepartmentSerializer(serializers.ModelSerializer): 45 """ 46 部门信息序列化 47 """ 48 class Meta: 49 model = Department 50 fields = '__all__' 51 52 53 class DepartmentDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 54 """ 55 部门信息反序列化 56 """ 57 class Meta: 58 model = Department 59 fields = '__all__' 60 list_serializer_class = BulkListSerializer 61 62 63 class ProjectSerializer(serializers.ModelSerializer): 64 """ 65 项目信息序列化 66 """ 67 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 68 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 69 creator = UserSerializer() 70 updater = UserSerializer() 71 department = DepartmentSerializer() 72 73 class Meta: 74 model = Project 75 fields = '__all__' 76 77 78 class ProjectDetailSerializer(serializers.ModelSerializer): 79 """ 80 项目信息序列化 81 """ 82 toUpdateApiCount = serializers.SerializerMethodField() 83 toVerifyApiCount = serializers.SerializerMethodField() 84 updatedApiCount = serializers.SerializerMethodField() 85 apiCount = serializers.SerializerMethodField() 86 apiNoCaseCount = serializers.SerializerMethodField() 87 apiCoverage = serializers.SerializerMethodField() 88 apiPassRate = serializers.SerializerMethodField() 89 stepCount = serializers.SerializerMethodField() 90 dynamicCount = serializers.SerializerMethodField() 91 memberCount = serializers.SerializerMethodField() 92 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 93 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 94 creator = UserSerializer() 95 updater = UserSerializer() 96 department = DepartmentSerializer() 97 98 class Meta: 99 model = Project 100 fields = ('id', 'name', 'version', 'department', 101 'create_time', 'update_time', 'delete_time', 'is_delete', 'status', 'description', 102 'creator', 'updater', 'apiCount', 'apiNoCaseCount', 'apiCoverage', 'stepCount', 103 'apiPassRate', 'toUpdateApiCount', 'toVerifyApiCount', 'updatedApiCount', 104 'dynamicCount', 'memberCount') 105 106 def get_apiCount(self, obj): 107 return obj.api_project.filter(status__exact=True).count() 108 109 def get_apiNoCaseCount(self, obj): 110 api_no_case_count = 0 111 for api in obj.api_project.filter(status__exact=True): 112 steps = api.step_api.filter(status__exact=True) 113 if steps.count() == 0: 114 # 接口无测试步骤 115 api_no_case_count += 1 116 return api_no_case_count 117 118 def get_apiPassCount(self, obj): 119 api_pass_count = 0 120 for api in obj.api_project.filter(status__exact=True): 121 steps = api.step_api.filter(status__exact=True) 122 if steps.count() == 0: 123 # 接口无测试步骤 124 continue 125 fail_steps = steps.exclude(result__exact='passed') 126 if fail_steps.count() == 0: 127 # 步骤全部通过 128 api_pass_count += 1 129 return api_pass_count 130 131 def get_apiPassRate(self, obj): 132 api_count = self.get_apiCount(obj) 133 if api_count == 0: 134 return 1 135 pass_count = self.get_apiPassCount(obj) 136 return round(pass_count / api_count, 3) 137 138 def get_apiCoverage(self, obj): 139 api_count = obj.api_project.filter(status__exact=True).count() 140 if api_count == 0: 141 return 1 142 143 api_count_with_case = 0 144 for api in obj.api_project.filter(status__exact=True): 145 if api.step_api.filter(status__exact=True).count() > 0: 146 api_count_with_case += 1 147 return round(api_count_with_case/api_count, 3) 148 149 def get_toUpdateApiCount(self, obj): 150 to_update_api_count = 0 151 for api in obj.api_project.filter(status__exact=True): 152 updates = api.update_api.filter(api__id__exact=api.id) 153 update_status_list = [u.update_status for u in updates] 154 if update_status_list and min(update_status_list) == 0: 155 to_update_api_count += 1 156 return to_update_api_count 157 # return obj.api_project.filter(update_status__exact=0, status__exact=True).count() 158 159 def get_toVerifyApiCount(self, obj): 160 to_verify_api_count = 0 161 for api in obj.api_project.filter(status__exact=True): 162 updates = api.update_api.filter(api__id__exact=api.id) 163 update_status_list = [u.update_status for u in updates] 164 if update_status_list and min(update_status_list) == 1: 165 to_verify_api_count += 1 166 return to_verify_api_count 167 # return obj.api_project.filter(update_status__exact=1, status__exact=True).count() 168 169 def get_updatedApiCount(self, obj): 170 updated_api_count = 0 171 for api in obj.api_project.filter(status__exact=True): 172 updates = api.update_api.filter(api__id__exact=api.id) 173 update_status_list = [u.update_status for u in updates] 174 if not update_status_list or min(update_status_list) == 2: 175 updated_api_count += 1 176 return updated_api_count 177 # return obj.api_project.filter(update_status__exact=2, status__exact=True).count() 178 179 def get_stepCount(self, obj): 180 # return obj.case_project.filter(status__exact=True).count() 181 case_count = 0 182 for api in obj.api_project.filter(status__exact=True): 183 case_count += api.step_api.filter(status__exact=True).count() 184 return case_count 185 186 def get_dynamicCount(self, obj): 187 return obj.dynamic_project.all().count() 188 189 def get_memberCount(self, obj): 190 return obj.member_project.all().count() 191 192 193 class ProjectDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 194 """ 195 项目信息反序列化 196 """ 197 class Meta: 198 model = Project 199 fields = '__all__' 200 list_serializer_class = BulkListSerializer 201 202 203 class ProjectDynamicDeserializer(serializers.ModelSerializer): 204 """ 205 项目动态信息反序列化 206 """ 207 class Meta: 208 model = ProjectDynamic 209 fields = ('id', 'project', 'time', 'type', 'operationObject', 'user', 'description') 210 211 212 class ProjectDynamicSerializer(serializers.ModelSerializer): 213 """ 214 项目动态信息序列化 215 """ 216 operationUser = serializers.CharField(source='user.first_name') 217 time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 218 219 class Meta: 220 model = ProjectDynamic 221 fields = ('id', 'time', 'type', 'operationObject', 'operationUser', 'description') 222 223 224 class ProjectMemberDeserializer(serializers.ModelSerializer): 225 """ 226 项目成员信息反序列化 227 """ 228 class Meta: 229 model = ProjectMember 230 fields = ('id', 'role', 'status', 'project', 'user') 231 232 233 class ProjectMemberSerializer(serializers.ModelSerializer): 234 """ 235 项目成员信息序列化 236 """ 237 user = UserSerializer(read_only=True) 238 239 class Meta: 240 model = ProjectMember 241 fields = ('id', 'role', 'status', 'project', 'user') 242 243 244 class AppSettingSerializer(serializers.ModelSerializer): 245 """ 246 env信息序列化 247 """ 248 data = serializers.JSONField() 249 250 class Meta: 251 model = AppSetting 252 fields = '__all__' 253 254 255 class GlobalEnvSerializer(BulkSerializerMixin, serializers.ModelSerializer): 256 """ 257 env信息序列化 258 """ 259 config = serializers.JSONField() 260 data = serializers.JSONField() 261 mock = serializers.JSONField() 262 263 class Meta: 264 model = GlobalEnv 265 fields = '__all__' 266 list_serializer_class = BulkListSerializer 267 268 269 class GlobalConstSerializer(BulkSerializerMixin, serializers.ModelSerializer): 270 """ 271 global const信息序列化 272 """ 273 274 class Meta: 275 model = GlobalConst 276 fields = '__all__' 277 list_serializer_class = BulkListSerializer 278 279 280 class GlobalHeaderSerializer(BulkSerializerMixin, serializers.ModelSerializer): 281 """ 282 global const信息序列化 283 """ 284 285 class Meta: 286 model = GlobalHeader 287 fields = '__all__' 288 list_serializer_class = BulkListSerializer 289 290 291 class GlobalResponseValidateSerializer(BulkSerializerMixin, serializers.ModelSerializer): 292 """ 293 GlobalResponseValidate信息序列化 294 """ 295 296 class Meta: 297 model = GlobalResponseValidate 298 fields = '__all__' 299 list_serializer_class = BulkListSerializer 300 301 302 class GlobalLabelSerializer(BulkSerializerMixin, serializers.ModelSerializer): 303 """ 304 标签 信息序列化 305 """ 306 type_name = serializers.SerializerMethodField() 307 308 class Meta: 309 model = GlobalLabel 310 fields = ('id', 'name', 'type', 'type_name', 'status', 'description') 311 list_serializer_class = BulkListSerializer 312 313 def get_type_name(self, obj): 314 return obj.get_type_display() 315 316 317 class ApiGroupSerializer(serializers.ModelSerializer): 318 """ 319 接口一级分组信息序列化 320 """ 321 project = ProjectSerializer() 322 323 class Meta: 324 model = ApiGroup 325 fields = ('id', 'name', 'project', 326 'create_time', 'update_time', 'delete_time', 'is_delete', 'status', 'description') 327 328 329 class ApiGroupDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 330 """ 331 接口一级分组信息反序列化 332 """ 333 class Meta: 334 model = ApiGroup 335 fields = '__all__' 336 list_serializer_class = BulkListSerializer 337 338 339 class ApiInfoSerializer(serializers.ModelSerializer): 340 """ 341 接口详细信息序列化 342 """ 343 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 344 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 345 creator = UserSerializer() 346 updater = UserSerializer() 347 project = ProjectSerializer() 348 api_group = ApiGroupSerializer() 349 labels = GlobalLabelSerializer(many=True, read_only=True) 350 update_status_name = serializers.SerializerMethodField() 351 test_case_count = serializers.SerializerMethodField() 352 353 class Meta: 354 model = ApiInfo 355 fields = ('id', 'yapi_id', 'project', 'api_group', 'origin', 'name', 'http_type', 'method', 'path', 'host_tag', 356 'yapi_req_headers', 'yapi_req_params', 'yapi_req_query', 'yapi_req_body_form', 'yapi_req_body_other', 'yapi_res_body', 357 'req_headers', 'req_params', 'req_json', 'req_data', 'validator', 'update_status', 'labels', 358 'create_time', 'update_time', 'delete_time', 'is_delete', 'status', 'description', 359 'creator', 'updater', 'update_status_name', 'test_case_count') 360 361 def get_update_status_name(self, obj): 362 return obj.get_update_status_display() 363 364 def get_test_case_count(self, obj): 365 return obj.step_api.all().count() 366 367 368 class ApiInfoCountSerializer(serializers.ModelSerializer): 369 """接口统计信息序列化""" 370 api_count = serializers.SerializerMethodField() 371 toUpdateApiCount = serializers.SerializerMethodField() 372 toVerifyApiCount = serializers.SerializerMethodField() 373 updatedApiCount = serializers.SerializerMethodField() 374 375 376 class ApiInfoDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 377 """ 378 接口详细信息序列化 379 """ 380 class Meta: 381 model = ApiInfo 382 fields = '__all__' 383 list_serializer_class = BulkListSerializer 384 385 386 class ApiUpdateHistorySerializer(serializers.ModelSerializer): 387 """ 388 接口变更历史信息序列化 389 """ 390 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 391 update_status_name = serializers.SerializerMethodField() 392 393 class Meta: 394 model = ApiUpdateHistory 395 fields = ('id', 'api', 'event', 'content', 'updater', 'update_time', 'update_status', 'update_status_name') 396 397 def get_update_status_name(self, obj): 398 return obj.get_update_status_display() 399 400 401 class ApiUpdateHistoryDeserializer(serializers.ModelSerializer): 402 """ 403 接口变更历史信息反序列化 404 """ 405 class Meta: 406 model = ApiUpdateHistory 407 fields = ('id', 'api', 'event', 'content', 'updater', 'update_time', 'update_status') 408 409 410 class YApiEventSerializer(BulkSerializerMixin, serializers.ModelSerializer): 411 """ 412 YAPI变更事件信息序列化 413 """ 414 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 415 416 class Meta: 417 model = YApiEvent 418 fields = '__all__' 419 list_serializer_class = BulkListSerializer 420 421 422 class TestSuiteSerializer(serializers.ModelSerializer): 423 """ 424 测试用例集 信息序列化 425 """ 426 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 427 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 428 creator = UserSerializer() 429 updater = UserSerializer() 430 labels = GlobalLabelSerializer(many=True, read_only=True) 431 department = DepartmentSerializer() 432 433 class Meta: 434 model = TestSuite 435 fields = '__all__' 436 437 438 class TestSuiteDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 439 """ 440 测试用例集 信息序列化 441 """ 442 443 class Meta: 444 model = TestSuite 445 fields = '__all__' 446 list_serializer_class = BulkListSerializer 447 448 449 class TestCaseSerializer(serializers.ModelSerializer): 450 """ 451 测试用例 信息序列化 452 """ 453 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 454 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 455 creator = UserSerializer() 456 updater = UserSerializer() 457 test_suite = TestSuiteSerializer() 458 labels = GlobalLabelSerializer(many=True, read_only=True) 459 460 class Meta: 461 model = TestCase 462 fields = '__all__' 463 464 465 class TestCaseDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 466 """ 467 用例信息反序列化 468 """ 469 class Meta: 470 model = TestCase 471 fields = '__all__' 472 list_serializer_class = BulkListSerializer 473 474 475 class TestStepBaseSerializer(serializers.ModelSerializer): 476 """ 477 测试用例步骤 信息序列化 478 """ 479 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 480 update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 481 creator = UserSerializer() 482 updater = UserSerializer() 483 test_case = TestCaseSerializer() 484 apiInfo = ApiInfoSerializer() 485 labels = GlobalLabelSerializer(many=True, read_only=True) 486 487 class Meta: 488 model = TestStep 489 fields = '__all__' 490 491 492 class TestStepDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 493 """ 494 用例步骤信息反序列化 495 """ 496 class Meta: 497 model = TestStep 498 fields = '__all__' 499 list_serializer_class = BulkListSerializer 500 501 502 class TestStepSerializer(TestStepBaseSerializer): 503 depends = TestStepDeserializer(many=True, read_only=True) 504 505 506 class TestReportSerializer(BulkSerializerMixin, serializers.ModelSerializer): 507 """ 508 测试结果 信息序列化 509 """ 510 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 511 env = GlobalEnvSerializer() 512 513 class Meta: 514 model = TestReport 515 fields = '__all__' 516 list_serializer_class = BulkListSerializer 517 518 519 class TestReportDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 520 """ 521 测试结果 反信息序列化 522 """ 523 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 524 525 class Meta: 526 model = TestReport 527 fields = '__all__' 528 list_serializer_class = BulkListSerializer 529 530 531 class TestTaskSerializer(BulkSerializerMixin, serializers.ModelSerializer): 532 """ 533 测试任务 信息序列化 534 """ 535 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 536 test_env = GlobalEnvSerializer() 537 test_validate = GlobalResponseValidateSerializer(read_only=True) 538 539 class Meta: 540 model = TestTask 541 fields = '__all__' 542 list_serializer_class = BulkListSerializer 543 544 545 class TestTaskDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 546 """ 547 测试任务 信息序列化 548 """ 549 create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) 550 551 class Meta: 552 model = TestTask 553 fields = '__all__' 554 list_serializer_class = BulkListSerializer 555 556 557 class TestEnvMonitorSerializer(BulkSerializerMixin, serializers.ModelSerializer): 558 """ 559 测试环境验证、状态监控 信息序列化 560 """ 561 env = GlobalEnvSerializer() 562 validate = GlobalResponseValidateSerializer() 563 report = TestReportSerializer() 564 565 class Meta: 566 model = TestEnvMonitor 567 fields = '__all__' 568 list_serializer_class = BulkListSerializer 569 570 571 class TestEnvMonitorDeserializer(BulkSerializerMixin, serializers.ModelSerializer): 572 """ 573 测试环境验证、状态监控 反信息序列化 574 """ 575 class Meta: 576 model = TestEnvMonitor 577 fields = '__all__' 578 list_serializer_class = BulkListSerializer 579 580 581 if __name__ == '__main__': 582 pass
三、为每个表数据编写自定义FilterSet,以应付可能需要的复杂过滤查询
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:filters.py 6 @time:2021/09/08 7 @email:tao.xu2008@outlook.com 8 @description: 过滤器 9 """ 10 11 import django_filters 12 from django_filters.rest_framework import FilterSet 13 from django.utils.translation import gettext_lazy as _ 14 15 from apps.api_test.models import Project, ProjectMember, \ 16 GlobalConst, GlobalEnv, GlobalHeader, GlobalLabel, GlobalResponseValidate, \ 17 ApiGroup, ApiInfo, ApiUpdateHistory, YApiEvent, \ 18 TestSuite, TestCase, TestStep, TestReport, TestTask, TestEnvMonitor 19 20 21 class BaseAnyInFilter(django_filters.Filter): 22 """TODO""" 23 def __init__(self, *args, **kwargs): 24 kwargs.setdefault('lookup_expr', 'any_in') 25 kwargs.setdefault('help_text', _('Multiple values may be separated by commas.')) 26 super().__init__(*args, **kwargs) 27 28 class ConcreteCSVField(self.base_field_class, self.field_class): 29 pass 30 31 ConcreteCSVField.__name__ = self._field_class_name( 32 self.field_class, self.lookup_expr 33 ) 34 35 self.field_class = ConcreteCSVField 36 37 38 class NumberAnyInFilter(BaseAnyInFilter, django_filters.NumberFilter): 39 pass 40 41 42 class NumberInFilter(django_filters.BaseInFilter, django_filters.NumberFilter): 43 pass 44 45 46 class ProjectFilter(FilterSet): 47 name = django_filters.CharFilter(field_name='name', lookup_expr='icontains') 48 id_in = NumberInFilter(field_name='id', lookup_expr='in') 49 department__isnull = django_filters.CharFilter(field_name='department__id', lookup_expr='isnull') 50 51 class Meta: 52 model = Project 53 fields = { 54 'name': ['icontains'], 55 'department': ['exact'] 56 } 57 58 59 class ProjectMemberFilter(FilterSet): 60 id_in = NumberInFilter(field_name='id', lookup_expr='in') 61 user__username = django_filters.CharFilter(field_name='user__username', lookup_expr='icontains') 62 63 class Meta: 64 model = ProjectMember 65 fields = { 66 'project': ['exact'], 67 'status': ['exact'], 68 'role': ['exact'], 69 } 70 71 72 class GlobalConstFilter(FilterSet): 73 id_in = NumberInFilter(field_name='id', lookup_expr='in') 74 75 class Meta: 76 model = GlobalConst 77 fields = { 78 'name': ['exact'] 79 } 80 81 82 class GlobalEnvFilter(FilterSet): 83 id_in = NumberInFilter(field_name='id', lookup_expr='in') 84 name_icontains = django_filters.CharFilter(field_name='name', lookup_expr='icontains') 85 86 class Meta: 87 model = GlobalEnv 88 fields = { 89 'name': ['exact'] 90 } 91 92 93 class GlobalHeaderFilter(FilterSet): 94 id_in = NumberInFilter(field_name='id', lookup_expr='in') 95 96 class Meta: 97 model = GlobalHeader 98 fields = { 99 'name': ['exact'] 100 } 101 102 103 class GlobalLabelFilter(FilterSet): 104 id_in = NumberInFilter(field_name='id', lookup_expr='in') 105 status = django_filters.BooleanFilter(field_name='status', lookup_expr='exact') 106 107 class Meta: 108 model = GlobalLabel 109 fields = { 110 'name': ['exact'], 111 'type': ['exact'] 112 } 113 114 115 class GlobalResponseValidateFilter(FilterSet): 116 id_in = NumberInFilter(field_name='id', lookup_expr='in') 117 118 class Meta: 119 model = GlobalResponseValidate 120 fields = { 121 'name': ['exact'] 122 } 123 124 125 class ApiGroupFilter(FilterSet): 126 id_in = NumberInFilter(field_name='id', lookup_expr='in') 127 128 class Meta: 129 model = ApiGroup 130 fields = { 131 'name': ['icontains'], 132 'project': ['exact'] 133 } 134 135 136 class ApiInfoFilter(FilterSet): 137 id_in = NumberInFilter(field_name='id', lookup_expr='in') 138 name_icontains = django_filters.CharFilter(field_name='name', lookup_expr='icontains') 139 path_icontains = django_filters.CharFilter(field_name='path', lookup_expr='icontains') 140 project__isnull = django_filters.Filter(field_name='project', lookup_expr='isnull') 141 api_group__isnull = django_filters.Filter(field_name='api_group', lookup_expr='isnull') 142 project__id__in = NumberInFilter(field_name='project__id', lookup_expr='in') 143 update_status__in = NumberInFilter(field_name='update_status', lookup_expr='in') 144 update_status__gt = django_filters.BooleanFilter(field_name='update_status', lookup_expr='gt') 145 step_api__id__isnull = django_filters.BooleanFilter(field_name='step_api__id', lookup_expr='isnull') 146 create_time__gte = django_filters.DateFilter(field_name='create_time', lookup_expr='gte') 147 create_time__lte = django_filters.DateFilter(field_name='create_time', lookup_expr='lte') 148 149 class Meta: 150 model = ApiInfo 151 fields = { 152 'name': ['exact'], 153 'path': ['exact'], 154 'project': ['exact'], 155 'api_group': ['exact'], 156 'api_group_id': ['exact'], 157 'update_status': ['exact'], 158 } 159 160 161 class ApiUpdateHistoryFilter(FilterSet): 162 id_in = NumberInFilter(field_name='id', lookup_expr='in') 163 api__id__in = NumberInFilter(field_name='api__id', lookup_expr='in') 164 update_status__in = NumberInFilter(field_name='update_status', lookup_expr='in') 165 update_status__gt = django_filters.BooleanFilter(field_name='update_status', lookup_expr='gt') 166 167 class Meta: 168 model = ApiUpdateHistory 169 fields = { 170 'id': ['icontains'], 171 'api__id': ['exact'], 172 'update_status': ['exact'] 173 } 174 175 176 class YApiEventFilter(FilterSet): 177 id_in = NumberInFilter(field_name='id', lookup_expr='in') 178 179 class Meta: 180 model = YApiEvent 181 fields = { 182 'id': ['icontains'], 183 'yapi_id': ['exact'], 184 'event': ['exact'] 185 } 186 187 188 class TestSuiteFilter(FilterSet): 189 id_in = NumberInFilter(field_name='id', lookup_expr='in') 190 name = django_filters.CharFilter(field_name='name', lookup_expr='icontains') 191 department__in = NumberInFilter(field_name='department__id', lookup_expr='in') 192 department__isnull = django_filters.CharFilter(field_name='department__id', lookup_expr='isnull') 193 labels__in = django_filters.BaseInFilter(field_name='labels', lookup_expr='in') 194 195 class Meta: 196 model = TestSuite 197 fields = { 198 'id': ['exact'], 199 'name': ['icontains'], 200 'department': ['exact'] 201 } 202 203 204 class TestCaseFilter(FilterSet): 205 id_in = NumberInFilter(field_name='id', lookup_expr='in') 206 name = django_filters.CharFilter(field_name='name', lookup_expr='icontains') 207 type__in = django_filters.BaseInFilter(field_name='type', lookup_expr='in') 208 result__in = django_filters.BaseInFilter(field_name='result', lookup_expr='in') 209 test_suite__in = NumberInFilter(field_name='test_suite', lookup_expr='in') 210 department__in = NumberInFilter(field_name='test_suite__department__id', lookup_expr='in') 211 label__contains = django_filters.NumberFilter(field_name='labels__id', lookup_expr='contains') 212 labels__name__contains = django_filters.CharFilter(field_name='labels__name', lookup_expr='contains') 213 create_time__gte = django_filters.DateFilter(field_name='create_time', lookup_expr='gte') 214 create_time__lte = django_filters.DateFilter(field_name='create_time', lookup_expr='lte') 215 216 class Meta: 217 model = TestCase 218 fields = { 219 'id': ['exact'], 220 'name': ['icontains'], 221 'type': ['exact'], 222 'test_suite': ['exact'] 223 } 224 225 226 class TestStepFilter(FilterSet): 227 name = django_filters.CharFilter(field_name='name', lookup_expr='icontains') 228 description = django_filters.CharFilter(field_name='description', lookup_expr='icontains') 229 id_in = NumberInFilter(field_name='id', lookup_expr='in') 230 result__in = django_filters.BaseInFilter(field_name='result', lookup_expr='in') 231 test_case__in = NumberInFilter(field_name='test_case', lookup_expr='in') 232 apiInfo__in = NumberInFilter(field_name='apiInfo', lookup_expr='in') 233 apiInfo__project__in = NumberInFilter(field_name='apiInfo__project', lookup_expr='in') 234 department__in = NumberInFilter(field_name='test_case__test_suite__department', lookup_expr='in') 235 create_time__gte = django_filters.DateFilter(field_name='create_time', lookup_expr='gte') 236 create_time__lte = django_filters.DateFilter(field_name='create_time', lookup_expr='lte') 237 238 class Meta: 239 model = TestStep 240 fields = { 241 'id': ['exact'], 242 'name': ['exact'], 243 'description': ['icontains'], 244 'test_case': ['exact'], 245 'apiInfo__id': ['exact'], 246 'apiInfo__project__id': ['exact'] 247 } 248 249 250 class TestReportFilter(FilterSet): 251 id_in = NumberInFilter(field_name='id', lookup_expr='in') 252 create_time__gte = django_filters.DateTimeFilter(field_name='create_time', lookup_expr='gte') 253 create_time__lte = django_filters.DateTimeFilter(field_name='create_time', lookup_expr='lte') 254 255 class Meta: 256 model = TestReport 257 fields = { 258 'id': ['exact'], 259 'status': ['exact'], 260 'env': ['exact'], 261 'build_type': ['exact'] 262 } 263 264 265 class TestTaskFilter(FilterSet): 266 id_in = NumberInFilter(field_name='id', lookup_expr='in') 267 create_time__gte = django_filters.DateTimeFilter(field_name='create_time', lookup_expr='gte') 268 create_time__lte = django_filters.DateTimeFilter(field_name='create_time', lookup_expr='lte') 269 270 class Meta: 271 model = TestTask 272 fields = { 273 'id': ['exact'], 274 'status': ['exact'], 275 } 276 277 278 class TestEnvMonitorFilter(FilterSet): 279 id_in = NumberInFilter(field_name='id', lookup_expr='in') 280 build_type = django_filters.CharFilter(field_name='build_type', lookup_expr='exact') 281 env_name_icontains = django_filters.CharFilter(field_name='env__name', lookup_expr='icontains') 282 create_time__gte = django_filters.DateTimeFilter(field_name='create_time', lookup_expr='gte') 283 create_time__lte = django_filters.DateTimeFilter(field_name='create_time', lookup_expr='lte') 284 285 class Meta: 286 model = TestEnvMonitor 287 fields = { 288 'id': ['exact'], 289 'status': ['exact'], 290 'build_type': ['exact'], 291 } 292 293 294 if __name__ == '__main__': 295 pass
四、ViewSet,实现接口请求
test_suite、test_case、test_step为例:
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:test_suite.py 6 @time:2021/09/01 7 @email:tao.xu@outlook.com 8 @description: 9 """ 10 from apps.api_test.view_set.base import ApiTestBaseViewSet, GroupCountModelMixin, TotalCountModelMixin 11 from apps.api_test.models import TestSuite 12 from apps.api_test.serializers import TestSuiteSerializer, TestSuiteDeserializer 13 from apps.api_test.filters import TestSuiteFilter 14 15 16 class TestSuiteViewSet(ApiTestBaseViewSet): 17 serializer_class = TestSuiteSerializer 18 queryset = TestSuite.objects.all().order_by('id') 19 filterset_class = TestSuiteFilter 20 21 # 创建数据 22 def create(self, request, *args, **kwargs): 23 self.serializer_class = TestSuiteDeserializer 24 return super().create(request, *args, **kwargs) 25 26 # 更新数据 27 def update(self, request, *args, **kwargs): 28 self.serializer_class = TestSuiteDeserializer 29 return super().update(request, *args, **kwargs) 30 31 # 局部更新数据 32 def partial_update(self, request, *args, **kwargs): 33 self.serializer_class = TestSuiteDeserializer 34 return super().update(request, *args, **kwargs) 35 36 # 批量 更新数据 37 def bulk_update(self, request, *args, **kwargs): 38 self.serializer_class = TestSuiteDeserializer 39 return super().bulk_update(request, *args, **kwargs) 40 41 # 批量 局部更新数据 42 def partial_bulk_update(self, request, *args, **kwargs): 43 self.serializer_class = TestSuiteDeserializer 44 return super().partial_bulk_update(request, *args, **kwargs) 45 46 # 批量 删除数据 47 def bulk_destroy(self, request, *args, **kwargs): 48 self.serializer_class = TestSuiteDeserializer 49 return super().bulk_destroy(request, *args, **kwargs) 50 51 52 # 统计数据 53 class TestSuiteTotalViewSet(TotalCountModelMixin): 54 """获取接口总数数据""" 55 filterset_class = TestSuiteFilter 56 queryset = TestSuite.objects.filter(status__exact=True) 57 58 59 class TestSuiteCountViewSet(GroupCountModelMixin): 60 """获取测试用例集统计数据""" 61 filterset_class = TestSuiteFilter 62 queryset = TestSuite.objects.filter(status__exact=True) 63 default_group_by_field = 'department' 64 default_time_unit = None 65 66 67 if __name__ == '__main__': 68 pass
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:test_case.py 6 @time:2021/09/01 7 @email:tao.xu2008@outlook.com 8 @description: 9 """ 10 from apps.api_test.view_set.base import ApiTestBaseViewSet, GroupCountModelMixin, TotalCountModelMixin 11 from apps.api_test.models import TestCase 12 from apps.api_test.filters import TestCaseFilter 13 from apps.api_test.serializers import TestCaseSerializer, TestCaseDeserializer 14 15 16 class TestCaseViewSet(ApiTestBaseViewSet): 17 serializer_class = TestCaseSerializer 18 queryset = TestCase.objects.all().order_by('id') 19 filterset_class = TestCaseFilter 20 21 # 查询数据 22 def list(self, request, *args, **kwargs): 23 return super().list(request, *args, **kwargs) 24 25 # 更新数据 26 def update(self, request, *args, **kwargs): 27 self.serializer_class = TestCaseDeserializer 28 return super().update(request, *args, **kwargs) 29 30 # 局部更新数据 31 def partial_update(self, request, *args, **kwargs): 32 self.serializer_class = TestCaseDeserializer 33 return super().update(request, *args, **kwargs) 34 35 # 创建数据 36 def create(self, request, *args, **kwargs): 37 self.serializer_class = TestCaseDeserializer 38 return super().create(request, *args, **kwargs) 39 40 # 批量 更新数据 41 def bulk_update(self, request, *args, **kwargs): 42 self.serializer_class = TestCaseDeserializer 43 return super().bulk_update(request, *args, **kwargs) 44 45 # 批量 局部更新数据 46 def partial_bulk_update(self, request, *args, **kwargs): 47 self.serializer_class = TestCaseDeserializer 48 return super().partial_bulk_update(request, *args, **kwargs) 49 50 # 批量 删除数据 51 def bulk_destroy(self, request, *args, **kwargs): 52 self.serializer_class = TestCaseDeserializer 53 return super().bulk_destroy(request, *args, **kwargs) 54 55 56 # 统计数据 57 class TestCaseTotalViewSet(TotalCountModelMixin): 58 """获取接口总数数据""" 59 filterset_class = TestCaseFilter 60 queryset = TestCase.objects.filter(status__exact=True) 61 62 63 class TestCaseCountViewSet(GroupCountModelMixin): 64 """获取测试用例统计数据""" 65 filterset_class = TestCaseFilter 66 queryset = TestCase.objects.filter(status__exact=True) 67 default_group_by_field = 'type' 68 default_time_unit = None 69 70 71 if __name__ == '__main__': 72 pass
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:test_case.py 6 @time:2021/09/01 7 @email:tao.xu@outlook.com 8 @description: 9 """ 10 from apps.api_test.view_set.base import ApiTestBaseViewSet, GroupCountModelMixin, TotalCountModelMixin 11 from apps.api_test.models import TestStep 12 from apps.api_test.filters import TestStepFilter 13 from apps.api_test.serializers import TestStepSerializer, TestStepDeserializer 14 15 16 class TestStepViewSet(ApiTestBaseViewSet): 17 serializer_class = TestStepSerializer 18 queryset = TestStep.objects.all().order_by('id') 19 filterset_class = TestStepFilter 20 21 # 查询数据 22 def list(self, request, *args, **kwargs): 23 return super().list(request, *args, **kwargs) 24 25 # 更新数据 26 def update(self, request, *args, **kwargs): 27 self.serializer_class = TestStepDeserializer 28 return super().update(request, *args, **kwargs) 29 30 # 局部更新数据 31 def partial_update(self, request, *args, **kwargs): 32 self.serializer_class = TestStepDeserializer 33 return super().update(request, *args, **kwargs) 34 35 # 创建数据 36 def create(self, request, *args, **kwargs): 37 self.serializer_class = TestStepDeserializer 38 return super().create(request, *args, **kwargs) 39 40 # 批量 更新数据 41 def bulk_update(self, request, *args, **kwargs): 42 self.serializer_class = TestStepDeserializer 43 return super().bulk_update(request, *args, **kwargs) 44 45 # 批量 局部更新数据 46 def partial_bulk_update(self, request, *args, **kwargs): 47 self.serializer_class = TestStepDeserializer 48 return super().partial_bulk_update(request, *args, **kwargs) 49 50 # 批量 删除数据 51 def bulk_destroy(self, request, *args, **kwargs): 52 self.serializer_class = TestStepDeserializer 53 return super().bulk_destroy(request, *args, **kwargs) 54 55 56 # 统计数据 57 class TestStepTotalViewSet(TotalCountModelMixin): 58 """获取接口总数数据""" 59 filterset_class = TestStepFilter 60 queryset = TestStep.objects.filter(status__exact=True) 61 62 63 class TestStepCountViewSet(GroupCountModelMixin): 64 """获取测试步骤统计数据""" 65 filterset_class = TestStepFilter 66 queryset = TestStep.objects.filter(status__exact=True) 67 default_group_by_field = 'result' 68 default_time_unit = None 69 70 71 if __name__ == '__main__': 72 pass
五、注册路由 urls.py
1 #!/usr/bin/python 2 # -*- coding:utf-8 _*- 3 """ 4 @author:TXU 5 @file:urls.py 6 @time:2021/08/23 7 @email:tao.xu2008@outlook.com 8 @description: 9 """ 10 11 from django.conf.urls import url 12 from django.urls import path, include 13 # from rest_framework.routers import DefaultRouter 14 from rest_framework_bulk.routes import BulkRouter 15 from apps.api_test.view_set.story.department import DepartmentViewSet 16 from apps.api_test.view_set.story.project import ProjectViewSet 17 from apps.api_test.view_set.story.project_member import ProjectMemberViewSet 18 from apps.api_test.view_set.global_config.app_setting import AppSettingViewSet, GetDefaultAppSettingView 19 from apps.api_test.view_set.global_config.global_env import GlobalEnvViewSet, EnvDataViewSet, \ 20 GetEnvDefaultConfigView, GetEnvDefaultQWExternalContactConfigView 21 from apps.api_test.view_set.global_config.global_header import GlobalHeaderViewSet 22 from apps.api_test.view_set.global_config.global_const import GlobalConstViewSet 23 from apps.api_test.view_set.global_config.global_label import GlobalLabelViewSet 24 from apps.api_test.view_set.global_config.global_response_validate import GlobalResponseValidateViewSet 25 from apps.api_test.view_set.api_view.api_info import ApiInfoViewSet, NoCaseApiInfoViewSet, ToDoApiInfoViewSet, \ 26 ApiTotalViewSet, ApiCountViewSet, NoCaseApiCountViewSet, WithCaseApiCountViewSet, ToDoApiCountViewSet 27 from apps.api_test.view_set.api_view.api_update_history import ApiUpdateHistoryViewSet, \ 28 ApiSyncUpdateStatusToHistoryViewSet 29 from apps.api_test.view_set.api_view.api_group import ApiGroupViewSet 30 from apps.api_test.view_set.api_view.yapi_event import YApiEventViewSet 31 from apps.api_test.view_set.update.yapi import YAPIEventMonitorView, YAPIEventDataSyncView, \ 32 APIDataSyncView, APICaseTemplateUpdateView 33 from apps.api_test.view_set.test_view.test_suite import TestSuiteViewSet, TestSuiteCountViewSet, TestSuiteTotalViewSet 34 from apps.api_test.view_set.test_view.test_case import TestCaseViewSet, TestCaseCountViewSet, TestCaseTotalViewSet 35 from apps.api_test.view_set.test_view.test_step import TestStepViewSet, TestStepCountViewSet, TestStepTotalViewSet 36 from apps.api_test.view_set.test_view.test_report import TestReportViewSet, PytestHtmlViewSet, JenkinsAllureViewSet, \ 37 TestLogsViewSet 38 from apps.api_test.view_set.test_view.test_env_monitor import TestEnvMonitorViewSet 39 from apps.api_test.view_set.task.test_task import TestTaskViewSet 40 from apps.api_test.view_set.upload.case_upload import UploadFileView 41 42 from apps.api_test.view_set.help.comparators import ComparatorHelpViewSet 43 from apps.api_test.view_set.help.functions import BuiltinFunctionHelpViewSet, CustomizedCallBackFunctionHelpViewSet, \ 44 CustomizedMallFunctionHelpViewSet, CustomizedSettingsFunctionHelpViewSet 45 46 from apps.api_test.view_set.runner.run import TestRunViewSet 47 48 # router = DefaultRouter() 49 router = BulkRouter() 50 51 # department 52 router.register(r'department/bulk', DepartmentViewSet), # 批量处理 53 router.register(r'department/list', DepartmentViewSet, basename='list'), 54 router.register(r'department/detail', DepartmentViewSet, basename='retrieve'), 55 router.register(r'department/add', DepartmentViewSet, basename='create'), 56 router.register(r'department/update', DepartmentViewSet, basename='update'), 57 router.register(r'department/del', DepartmentViewSet, basename='destroy') 58 59 # project 60 router.register(r'project/bulk', ProjectViewSet), # 批量处理 61 router.register(r'project/list', ProjectViewSet, basename='list'), 62 router.register(r'project/detail', ProjectViewSet, basename='retrieve'), 63 router.register(r'project/add', ProjectViewSet, basename='create'), 64 router.register(r'project/update', ProjectViewSet, basename='update'), 65 router.register(r'project/del', ProjectViewSet, basename='destroy') 66 67 # project member 68 router.register(r'project/member/list', ProjectMemberViewSet, basename='list'), 69 router.register(r'project/member/detail', ProjectMemberViewSet, basename='retrieve'), 70 router.register(r'project/member/add', ProjectMemberViewSet, basename='create'), 71 router.register(r'project/member/update', ProjectMemberViewSet, basename='update'), 72 router.register(r'project/member/del', ProjectMemberViewSet, basename='destroy') 73 74 # app系统配置 75 router.register(r'global/app_setting/list', AppSettingViewSet, basename='list'), 76 router.register(r'global/app_setting/detail', AppSettingViewSet, basename='retrieve'), 77 router.register(r'global/app_setting/add', AppSettingViewSet, basename='create'), 78 router.register(r'global/app_setting/update', AppSettingViewSet, basename='update'), 79 router.register(r'global/app_setting/del', AppSettingViewSet, basename='destroy'), 80 router.register(r'global/app_setting/data', GetDefaultAppSettingView, basename='retrieve'), 81 82 # global env 环境配置 83 router.register(r'global/env/bulk', GlobalEnvViewSet), 84 router.register(r'global/env/list', GlobalEnvViewSet, basename='list'), 85 router.register(r'global/env/detail', GlobalEnvViewSet, basename='retrieve'), 86 router.register(r'global/env/add', GlobalEnvViewSet, basename='create'), 87 router.register(r'global/env/update', GlobalEnvViewSet, basename='update'), 88 router.register(r'global/env/del', GlobalEnvViewSet, basename='destroy'), 89 router.register(r'global/env/data', EnvDataViewSet, basename='retrieve'), 90 91 # global header 92 router.register(r'global/header/bulk', GlobalHeaderViewSet), 93 router.register(r'global/header/list', GlobalHeaderViewSet, basename='list'), 94 router.register(r'global/header/detail', GlobalHeaderViewSet, basename='retrieve'), 95 router.register(r'global/header/add', GlobalHeaderViewSet, basename='create'), 96 router.register(r'global/header/update', GlobalHeaderViewSet, basename='update'), 97 router.register(r'global/header/del', GlobalHeaderViewSet, basename='destroy'), 98 99 # global const 100 router.register(r'global/const/bulk', GlobalConstViewSet), 101 router.register(r'global/const/list', GlobalConstViewSet, basename='list'), 102 router.register(r'global/const/detail', GlobalConstViewSet, basename='retrieve'), 103 router.register(r'global/const/add', GlobalConstViewSet, basename='create'), 104 router.register(r'global/const/update', GlobalConstViewSet, basename='update'), 105 router.register(r'global/const/del', GlobalConstViewSet, basename='destroy'), 106 107 # global label 108 router.register(r'global/label/bulk', GlobalLabelViewSet), 109 router.register(r'global/label/list', GlobalLabelViewSet, basename='list'), 110 router.register(r'global/label/detail', GlobalLabelViewSet, basename='retrieve'), 111 router.register(r'global/label/add', GlobalLabelViewSet, basename='create'), 112 router.register(r'global/label/update', GlobalLabelViewSet, basename='update'), 113 router.register(r'global/label/del', GlobalLabelViewSet, basename='destroy'), 114 115 # global response_validate 116 router.register(r'global/response_validate/bulk', GlobalResponseValidateViewSet), 117 router.register(r'global/response_validate/list', GlobalResponseValidateViewSet, basename='list'), 118 router.register(r'global/response_validate/detail', GlobalResponseValidateViewSet, basename='retrieve'), 119 router.register(r'global/response_validate/add', GlobalResponseValidateViewSet, basename='create'), 120 router.register(r'global/response_validate/update', GlobalResponseValidateViewSet, basename='update'), 121 router.register(r'global/response_validate/del', GlobalResponseValidateViewSet, basename='destroy'), 122 123 # api group 124 router.register(r'api/group/bulk', ApiGroupViewSet), 125 router.register(r'api/group/list', ApiGroupViewSet, basename='list'), 126 router.register(r'api/group/detail', ApiGroupViewSet, basename='retrieve'), 127 router.register(r'api/group/add', ApiGroupViewSet, basename='create'), 128 router.register(r'api/group/update', ApiGroupViewSet, basename='update'), 129 router.register(r'api/group/del', ApiGroupViewSet, basename='destroy'), 130 131 # api info 132 router.register(r'api/bulk', ApiInfoViewSet), 133 router.register(r'api/list', ApiInfoViewSet, basename='list'), 134 router.register(r'api/nocase/list', NoCaseApiInfoViewSet, basename='no_case_list'), 135 router.register(r'api/todo/list', ToDoApiInfoViewSet, basename='todo_list'), 136 router.register(r'api/detail', ApiInfoViewSet, basename='retrieve'), 137 router.register(r'api/add', ApiInfoViewSet, basename='create'), 138 router.register(r'api/update', ApiInfoViewSet, basename='update'), 139 router.register(r'api/del', ApiInfoViewSet, basename='destroy'), 140 router.register(r'api/total', ApiTotalViewSet, basename='list'), 141 router.register(r'api/count', ApiCountViewSet, basename='list'), 142 router.register(r'api/count/no_case', NoCaseApiCountViewSet, basename='list'), 143 router.register(r'api/count/with_case', WithCaseApiCountViewSet, basename='list'), 144 router.register(r'api/count/todo', ToDoApiCountViewSet, basename='list'), 145 146 # api update history 147 router.register(r'api/update_history/list', ApiUpdateHistoryViewSet, basename='list'), 148 router.register(r'api/update_history/detail', ApiUpdateHistoryViewSet, basename='retrieve'), 149 router.register(r'api/update_history/add', ApiUpdateHistoryViewSet, basename='create'), 150 router.register(r'api/update_history/update', ApiUpdateHistoryViewSet, basename='update'), 151 router.register(r'api/update_history/del', ApiUpdateHistoryViewSet, basename='destroy'), 152 153 # yapi event 154 router.register(r'api/yapi_event/bulk', YApiEventViewSet), 155 router.register(r'api/yapi_event/list', YApiEventViewSet, basename='list'), 156 router.register(r'api/yapi_event/detail', YApiEventViewSet, basename='retrieve'), 157 # router.register(r'api/yapi_event/add', YApiEventViewSet, basename='create'), # YAPIEventMonitorView 调用 158 router.register(r'api/yapi_event/update', YApiEventViewSet, basename='update'), 159 router.register(r'api/yapi_event/del', YApiEventViewSet, basename='destroy'), 160 161 # test suite 162 router.register(r'test/suite/bulk', TestSuiteViewSet), # 批量处理 163 router.register(r'test/suite/list', TestSuiteViewSet, basename='list'), 164 router.register(r'test/suite/detail', TestSuiteViewSet, basename='detail'), 165 router.register(r'test/suite/add', TestSuiteViewSet, basename='create'), 166 router.register(r'test/suite/update', TestSuiteViewSet, basename='update'), 167 router.register(r'test/suite/del', TestSuiteViewSet, basename='destroy'), 168 router.register(r'test/suite/total', TestSuiteTotalViewSet, basename='list'), 169 router.register(r'test/suite/count', TestSuiteCountViewSet, basename='list'), 170 171 # test case 172 router.register(r'test/case/bulk', TestCaseViewSet), # 批量处理 173 router.register(r'test/case/list', TestCaseViewSet, basename='list'), 174 router.register(r'test/case/detail', TestCaseViewSet, basename='retrieve'), 175 router.register(r'test/case/add', TestCaseViewSet, basename='create'), 176 router.register(r'test/case/update', TestCaseViewSet, basename='update'), 177 router.register(r'test/case/del', TestCaseViewSet, basename='destroy'), 178 router.register(r'test/case/total', TestCaseTotalViewSet, basename='list'), 179 router.register(r'test/case/count', TestCaseCountViewSet, basename='list'), 180 181 # test step 182 router.register(r'test/step/bulk', TestStepViewSet), # 批量处理 183 router.register(r'test/step/list', TestStepViewSet, basename='list'), 184 router.register(r'test/step/detail', TestStepViewSet, basename='retrieve'), 185 router.register(r'test/step/add', TestStepViewSet, basename='create'), 186 router.register(r'test/step/update', TestStepViewSet, basename='update'), 187 router.register(r'test/step/del', TestStepViewSet, basename='destroy'), 188 router.register(r'test/step/total', TestStepTotalViewSet, basename='list'), 189 router.register(r'test/step/count', TestStepCountViewSet, basename='list'), 190 191 # 测试执行 192 router.register(r'test/run', TestRunViewSet, basename='create'), 193 194 # 测试报告 195 router.register(r'test/report/bulk', TestReportViewSet), # 批量处理 196 router.register(r'test/report/list', TestReportViewSet, basename='list'), 197 router.register(r'test/report/detail', TestReportViewSet, basename='retrieve'), 198 router.register(r'test/report/update', TestReportViewSet, basename='update'), 199 router.register(r'test/report/pytest_html', PytestHtmlViewSet, basename='retrieve'), 200 router.register(r'test/report/jenkins_allure', JenkinsAllureViewSet, basename='retrieve'), 201 router.register(r'test/report/logs', TestLogsViewSet, basename='retrieve'), 202 203 # 测试环境验证、状态监控 204 router.register(r'test/env_monitor/bulk', TestEnvMonitorViewSet), # 批量处理 205 router.register(r'test/env_monitor/list', TestEnvMonitorViewSet, basename='list'), 206 router.register(r'test/env_monitor/detail', TestEnvMonitorViewSet, basename='retrieve'), 207 router.register(r'test/env_monitor/add', TestEnvMonitorViewSet, basename='create'), 208 router.register(r'test/env_monitor/update', TestEnvMonitorViewSet, basename='update'), 209 router.register(r'test/env_monitor/del', TestEnvMonitorViewSet, basename='destroy'), 210 211 # 测试任务 212 # router.register(r'test/task/bulk', TestTaskViewSet), # 批量处理 - 暂不支持 213 router.register(r'test/task/add', TestTaskViewSet, basename='create'), 214 router.register(r'test/task/update', TestTaskViewSet, basename='update'), 215 router.register(r'test/task/del', TestTaskViewSet, basename='destroy'), 216 router.register(r'test/task/list', TestTaskViewSet, basename='list'), 217 router.register(r'test/task/detail', TestTaskViewSet, basename='retrieve'), 218 219 # 帮助信息 220 router.register(r'help/comparator/list', ComparatorHelpViewSet, basename='list'), 221 router.register(r'help/builtin_functions/list', BuiltinFunctionHelpViewSet, basename='list') 222 router.register(r'help/callback_functions/list', CustomizedCallBackFunctionHelpViewSet, basename='list') 223 router.register(r'help/mall_functions/list', CustomizedMallFunctionHelpViewSet, basename='list') 224 router.register(r'help/settings_functions/list', CustomizedSettingsFunctionHelpViewSet, basename='list') 225 226 urlpatterns = [ 227 # path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), 228 229 # 数据表管理 230 path('', include(router.urls)), 231 232 # file xmind 233 url(r"file/upload", UploadFileView.as_view()), 234 # 获取env默认数据 235 url(r'global/env/config/default', GetEnvDefaultConfigView.as_view()), 236 url(r'global/env/qw_external_contact_config/default', GetEnvDefaultQWExternalContactConfigView.as_view()), 237 # YAPI事件监听 238 url(r'api/yapi_event/add', YAPIEventMonitorView.as_view()), 239 # YAPI事件数据同步到本地接口 240 url(r'api/yapi_event/data_sync', YAPIEventDataSyncView.as_view()), 241 # 本地接口拉取YAPI数据同步 242 url(r'api/data_sync', APIDataSyncView.as_view()), 243 # 本地接口用例模板更新 244 url(r'api/update/case_template', APICaseTemplateUpdateView.as_view()), 245 # 接口update_status同步到接口变更历史表 246 url(r'api/sync/update_history/update_status', ApiSyncUpdateStatusToHistoryViewSet.as_view()), 247 ] 248 249 250 if __name__ == '__main__': 251 pass
-------- THE END --------
rest_framework_bulk