接口开发、多进程--18
1、注册接口
1)views.py
1 class RegisterView(BaseView, PostView): 2 '''注册需要md5加密在写入到数据库中''' 3 model_class = models.User # 用哪个model类 4 form_class = forms.RegisterForm # 用哪个form类 5 6 def post(self, request): 7 form_obj = self.form(request.POST) 8 if form_obj.is_valid(): 9 # print(form_obj.cleaned_data) 10 # md5加密 11 md5_password = self.model.make_password(form_obj.cleaned_data['password']) 12 # 更新原有的cleaned_data 13 form_obj.cleaned_data['password'] = md5_password 14 # 再创建 15 # print(form_obj.cleaned_data) 16 self.model.objects.create(**form_obj.cleaned_data) 17 ret = NbResponse() # 默认请求成功 18 else: 19 ret = NbResponse(code=-1, msg=form_obj.error_format) 20 return ret
2)forms.py
1 # 注册的form验证 2 class RegisterForm(ModelForm, ExtendForm): 3 class Meta: 4 model = models.User 5 exclude = ['is_delete']
3)urls.py
path('register', views.RegisterView.as_view()),
2、项目管理接口
- 重点:重构
- 将用户名返回显示在创建人,实际数据库中外键自关联是根据user_id,需要重构
- 因为接口是get请求,所以我们重构get方法,路径 NbView--GetView,复制get方法后修改
- 接口文档查看接口返回内容:
(1)views.py
1 class ProjectView(NbView): 2 search_field = ["name"] # 根据哪些字段来搜索 3 filter_field = [] # 根据哪些字段来搜索 4 model_class = models.Project # 用哪个model类 5 form_class = forms.ProjectForm # 用哪个form类 6 # 重构内容,将get方法复制修改下 7 def get(self, request): 8 page_data, page_obj = self.get_query_set_page_data() # 获取分页之后的数据 9 data_list = [] 10 for instance in page_data: 11 model_dict = model_to_dict(instance, self.fields, self.exclude_fields) # 转成字典 12 # 外键关联user表,将username返回给user 13 model_dict['user'] = instance.user.username 14 data_list.append(model_dict) 15 return NbResponse(data=data_list, count=page_obj.count)
(2)forms.py
class ProjectForm(ModelForm,ExtendForm): '''项目表''' class Meta: model = models.Project exclude = ['is_delete']
(3)urls.py配置路径
1 path('project', views.ProjectView.as_view()),#项目
3、接口管理接口
同项目接口一样都是get请求,需要重构get方法
接口管理接口设计的返回值
(1)、views.py
1 class InterfaceView(NbView): 2 search_field = ["name"] # 根据哪些字段来搜索 3 filter_field = ['project'] # 根据哪些字段来搜索 4 model_class = models.Interface # 用哪个model类 5 form_class = forms.InterfaceForm # 用哪个form类 6 7 def get(self, request): 8 page_data, page_obj = self.get_query_set_page_data() # 获取分页之后的数据 9 data_list = [] 10 for instance in page_data: # 11 model_dict = model_to_dict(instance, self.fields, self.exclude_fields) # 转成字典 12 model_dict['user'] = instance.user.username 13 model_dict['project_name'] = instance.project.name 14 model_dict['project_id'] = instance.project.id 15 data_list.append(model_dict) 16 return NbResponse(data=data_list, count=page_obj.count)
(2)、forms.py
1 class InterfaceForm(ModelForm,ExtendForm): 2 '''接口表''' 3 class Meta: 4 model = models.Interface 5 exclude = ['is_delete']
(3)、urls.py
1 path('interface', views.InterfaceView.as_view()),#接口
4、用例管理接口
(1)、views.py
1 from sksystem.core.case_utils import get_premise_case,check_premise 2 class CaseView(NbView): 3 search_field = ["title"] # 根据哪些字段来搜索 4 filter_field = ['project'] # 根据哪些字段来搜索 5 model_class = models.Case # 用哪个model类 6 form_class = forms.CaseForm # 用哪个form类 7 8 def get(self, request): 9 page_data, page_obj = self.get_query_set_page_data() # 获取分页之后的数据 10 data_list = [] 11 for instance in page_data: # 12 model_dict = model_to_dict(instance, self.fields, self.exclude_fields) # 转成字典 13 model_dict['user'] = instance.user.username 14 model_dict['project_name'] = instance.project.name 15 model_dict['project_id'] = instance.project.id 16 model_dict['interface_name'] = instance.interface.name 17 model_dict['interface_id'] = instance.interface.id 18 model_dict['rely_case'] = get_premise_case(instance)#编辑的时候需要带出已经依赖的用例 19 data_list.append(model_dict) 20 return NbResponse(data=data_list, count=page_obj.count) 21 22 # 添加用例的时候选择依赖的用例,但是没有创建自关联的关系,添加保存的时候走的是post方法,走的是NbView默认post方法 23 # 由于需要创建依赖用例的自关联,所以需要重写post 24 def post(self, request): 25 form_obj = self.form(request.POST) 26 # 从request.POST将用例依赖的case取出来 27 rely_case = request.POST.get('rely_case') 28 if form_obj.is_valid(): 29 # 想要进行自关联绑定,需要具备依赖用用例的id、以及自己的id 就是case.id 30 case = self.model.objects.create(**form_obj.cleaned_data) 31 # 绑定自关联 创建自关联关系 32 for rely_case_id in json.loads(rely_case):#rely_case实际上是字符串,json.loads()转化成数组 33 models.CasePremise.objects.create(case_id=case.id, premise_case_id=rely_case_id)#创建关系 34 ret = NbResponse() # 默认请求成功 35 else: 36 ret = NbResponse(code=-1, msg=form_obj.error_format) 37 return ret 38 def put(self, request): 39 # 用例在更新时处理自关联的关系。 40 # 先清掉之前所有的关联,然后在重新创建 41 #外键子自关联 42 rely_case = request.PUT.get('rely_case') 43 instance = self.model.objects.get(id=request.PUT.get('id')) 44 form_obj = self.form(request.PUT, instance=instance) 45 print('form_obj的返回数据:', form_obj) # 添加的用例的全部信息 46 if form_obj.is_valid(): 47 # 通过当前用例 获取所有被依赖的用例 并删除 48 instance.case.all().delete() 49 # 重新建立自关联绑定关系 50 for item in json.loads(rely_case): 51 models.CasePremise.objects.create(case_id=instance.id, premise_case_id=item) 52 form_obj.save() 53 ret = NbResponse() # 默认请求成功 54 else: 55 ret = NbResponse(code=-1, msg=form_obj.error_format) 56 return ret
注意:单独新建了一个文件,然后将方法写在这个文件中/core/case_utils.py
********
方法:外键自关联
"rely_case": [
{
"id": 4,
"title": "用例数据3"
}, ]
1 from sksystem import models 2 3 4 def get_premise_case(instance): 5 qs = instance.case.all()#知道当前的case的依赖用例,返回的是列表 6 rely_cases = [] 7 for item in qs: 8 rely_cases.append({"id": item.premise_case.id, "title": item.premise_case.title}) 9 print(rely_cases) 10 return rely_cases
*********
添加用例的时候选择项目,需要返回当前项目下所有的用例
# 由于添加用例时,需要根据项目获取所有用例。因此开发/api/get_rely_case
1 class RelyCaseView(View): 2 '''GET /api/get_rely_case?project_id=4 HT 如果不带case_id 说明是添加,只需要将项目下的用例返回 3 /api/get_rely_case?project_id=4&case_id=7 # 如果带了caseid 说明是编辑,需要将这个case的依赖返回。 4 1、项目下还没有用例 直接返回 5 2、项目下已经有用例 6 { 7 "code": 0, 8 "msg": "操作成功", 9 "data": [ 10 { 11 "id": 2, 12 "title": "测试平台项目接口" 13 }, 14 { 15 "id": 1, 16 "title": "测试平台登录接口" 17 } 18 ] 19 } 20 ''' 21 22 def get(self, requests): 23 project_id = requests.GET.get('project_id') 24 case_id = requests.GET.get('case_id') 25 if case_id: 26 # 编辑操作 当前这条用例不可以返回 通过exclude 进行过滤,返回的数据不包括已经被删除的用例 27 qs_data = models.Case.objects.filter(project_id=project_id, is_delete=1).exclude(id=case_id).values('id', 28 'title') 29 else:#如果当前项目下没有用例,直接返回,当前项目下有用例,返回用例的id和title 30 qs_data = models.Case.objects.filter(project_id=project_id, is_delete=1).values('id', 'title') 31 return NbResponse(data=list(qs_data))
(2)、forms.py
1 class CaseForm(ModelForm, ExtendForm): 2 class Meta: 3 model = models.Case 4 exclude = ['is_delete', 'status']
(3)urls.py
path('case', views.CaseView.as_view()), path('get_rely_case', views.RelyCaseView.as_view()),
5、用例集合管理
(1)views.py
class CaseCollectionView(NbView): search_field = ["name"] # 根据哪些字段来搜索 filter_field = ['project'] # 根据哪些字段来搜索 model_class = models.CaseCollection # 用哪个model类 form_class = forms.CaseCollectionFrom # 用哪个form类 exclude_fields = ['is_delete', 'case'] # 返回的时候排除哪些字段 #和case存在多对多关系 # 查询多对多 # 正向 根据集合查集合下的用例 # print(coll_obj.case.all()) # # 反向 根据用例查所在集合 # print(case_obj_A.casecollection_set.all()) def get(self, request): page_data, page_obj = self.get_query_set_page_data() # 获取分页之后的数据 data_list = [] for instance in page_data: # model_dict = model_to_dict(instance, self.fields, self.exclude_fields) # 转成字典 model_dict['user'] = instance.user.username model_dict['project_name'] = instance.project.name model_dict['project_id'] = instance.project.id model_dict['case_count'] = instance.case.all().count()#用例数 查询多对多,正向查询--根据集合查几个下所有的用例 data_list.append(model_dict) return NbResponse(data=data_list, count=page_obj.count)
(2)forms.py
1 class CaseCollectionFrom(ModelForm, ExtendForm): 2 class Meta: 3 model = models.CaseCollection 4 exclude = ['is_delete', 'status','case']
(3)urls.py
1 path('case_collection', views.CaseCollectionView.as_view()),
5、加入用例接口--集合中添加用例时需要调用join_case 接口
(1)views.py
1 # 根据 项目和集合id 获取要选择的用例 2 class JoinCaseView(View): 3 def get(self, request): 4 ''' 5 #http://127.0.0.1:8000/api/join_case?project_id=6&id=3 6 { 7 "code": 0, 8 "msg": "操作成功", 9 "data": { 10 "all_case": [ 11 { 12 "id": 2, 13 "title": "测试平台项目接口" 14 }, 15 { 16 "id": 1, 17 "title": "测试平台登录接口" 18 } 19 ], 20 "join_case": [ 21 2, 22 1 23 ] 24 } 25 } 26 27 :param request: 28 :return: 29 30 1、根据项目id 返回当前项目下所有没有被删除的用例。 31 2、根据集合id 获取已经和集合创建关系的用例id。 32 ''' 33 project_id = request.GET.get('project_id') # 项目id 34 coll_id = request.GET.get('id') # 集合id 35 all_case = models.Case.objects.filter(project_id=project_id, is_delete=1).values('id', 'title')#根据项目id获取到当前项目下所有没有被删除的用例 36 # 获取集合 37 coll_obj = models.CaseCollection.objects.get(id=coll_id) 38 # 通过多对多的查询获取集合下的用例 只要id字段 39 join_case_qs = coll_obj.case.all().values('id') 40 join_case = [] # 具体返回的joincase 41 for item in join_case_qs: 42 join_case.append(item.get('id')) 43 data = { 44 "all_case": list(all_case), 45 "join_case": join_case 46 } 47 return NbResponse(data=data) 48 49 def post(self, request): 50 # http://127.0.0.1:8000/api/join_case 51 ''' 52 join_case_list: [11,9,8,7] 53 id: 3 54 55 56 :param request: 57 :return: 58 ''' 59 join_case_list = request.POST.get('join_case_list') 60 coll_id = request.POST.get('id') 61 coll_obj = models.CaseCollection.objects.get(id=coll_id) 62 # # 更新时第一种方案 清掉之前绑定的数据 63 # coll_obj.case.clear() 64 # for item in json.loads(join_case_list): 65 # coll_obj.case.add(item) 66 # 第二种方案 通过 set的方式进行创建和更新 67 coll_obj.case.set(json.loads(join_case_list)) 68 return NbResponse()
(2)urls.py
path('join_case', views.JoinCaseView.as_view()),
6、异步任务:
- 同步:用例运行,点击运行后,一直等待结果返回
- 异步:用例运行,点击运行后,返回信息:‘用例已经运行’,等会回来看结果就可以了
- pip install Celery
1、config.py中配置自己的redis
2、main.py 不用动,写好的
3、task.py
例子:简单的实现下异步任务:
1)、tasks.py
1 from celery.utils.log import get_task_logger 2 from celery_tasks.main import app #导入main.py中声明的app 3 4 logger = get_task_logger('django_server') 5 6 @app.task(name='run_caseymy') 7 def run_case(case_id,user_id): 8 import time 9 time.sleep(10) 10 print(case_id) 11 print(user_id)
启动celery 的服务
# mac同学
# celery -A celery_tasks.main worker -l info 普通启动
# celery multi start w1 -A celery_tasks.main -l info --logfile=logs/celerylog.log --pidfile=logs/celerypid.pid 后台运行
# celery flower -A celery_tasks.main 打开一个web页面启动 需要提前安装下flow 安装命令:pip install flower
# win同学
# pip install eventlet
# celery -A celery_tasks.main worker -l info -P eventlet
2)、app目录下的tests.py
3)运行:
先执行tests.py 执行后效果如图:
tasks.py会自动执行,效果如图:
7、运行操作:
1、urls.py
1 path('run', views.CaseRunView.as_view()),
2、view.py
1 class CaseRunView(View): 2 def post(self, request): 3 case_id = request.POST.get('case_id')#用例id 4 user_id = request.POST.get('user_id') 5 task_id = run_case.delay(case_id,user_id) 6 print(task_id) 7 8 return NbResponse()
3、tasks.py
1 from celery.utils.log import get_task_logger 2 from celery_tasks.main import app #导入main.py中声明的app 3 import time 4 logger = get_task_logger('django_server') 5 #用例运行 6 @app.task(name='run_caseymy') 7 def run_case(case_id,user_id): 8 task_id = run_case.request.id 9 print('task:id',task_id) 10 time.sleep(10) 11 print(case_id) 12 print(user_id)
重启celery服务:
celery -A celery_tasks.main worker -l info -P eventlet
重启项目:
效果:用例处点击运行按钮后,返回的task_id 可以对上
完善views.py后
1 class CaseRunView(View): 2 def post(self, request): 3 case_id = request.POST.get('case_id')#用例id 4 user_id = request.POST.get('user_id') 5 6 7 for item_id in json.loads(case_id): 8 # 当页面调用异步任务时,会返回一个唯一的任务id 9 task_id = run_case.delay(item_id, request.user.id) 10 print('当前用例的task_id',task_id) 11 models.Case.objects.filter(id=item_id).update(report_batch=task_id, status=3)#修改用例状态,3是运行中的状态 12 return NbResponse()
页面再次点击运行
8、集合运行
1、urls.py
path('run_collection', views.CollectionRunView.as_view()),
2、views.py
1 class CollectionRunView(View): 2 def post(self, request): 3 collect_id = request.POST.get('collect_id')#集合id 4 user_id = request.POST.get('user_id') 5 for item_id in json.loads(collect_id): 6 # 当页面调用异步任务时,会返回一个唯一的任务id 7 task_id = run_collection.delay(item_id, request.user.id) 8 print('集合的task_id',task_id) 9 models.CaseCollection.objects.filter(id=item_id).update(report_batch=task_id, status=3)#修改用例状态,3是运行中的状态 10 return NbResponse()
3、tasks.py
1 #集合运行 2 @app.task(name='run_collect') 3 def run_collection(collect_id, user_id): 4 task_id = run_collection.request.id 5 print('集合task:id', task_id) 6 time.sleep(10) 7 print(collect_id) 8 print(user_id)
后台点击运行后,集合状态更改成运行中