接口平台测试开发--day16

一、pycharm 从git拉取代码

  • 1、VCS--Get Versoin Controll

  • 2、具体配置内容

二、执行manage.py

1、pycharm路径

   

  • 2、创建项目startapp +项目名称
  • 例如:startapp sksystem
  • 3、为新创建的项目新增urls.py
  • earth/urls.py 增加路径
 1 from django.contrib import admin
 2 from django.urls import path, include
 3 from sksystem import urls as sksUrls
 4 from example import urls as urls
 5 
 6 
 7 urlpatterns = [
 8     path('admin/', admin.site.urls),
 9     path('example/',include(urls)),
10     path('api/', include(sksUrls)),  # 例子url,访问的时候就是/example/book
11 ]

 

或者这样修改,将不用的example去除

1 from django.contrib import admin
2 from django.urls import path, include
3 
4 #from sksystem import urls
5 
6 urlpatterns = [
7     path('admin/', admin.site.urls),
8     path('api/', include(urls)),  # 例子url,访问的时候就是/example/book
9 ]

 

 4、settings.py 增加新增的项目

三、数据库设计:

 

 

 

 

 

 

 

 

models.py

  1 from django.db import models
  2 from utils import tools
  3 from earth import settings
  4 
  5 
  6 # Create your models here.
  7 
  8 
  9 class BaseModel(models.Model):
 10     '''公共字段'''
 11     is_delete_choice = (
 12         (0, '删除'),
 13         (1, '正常')
 14     )
 15     is_delete = models.SmallIntegerField(choices=is_delete_choice, default=1, verbose_name='是否被删除')
 16     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)  # auto_now_add的意思,插入数据的时候,自动取当前时间
 17     update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)  # 修改数据的时候,时间会自动变
 18 
 19     class Meta:
 20         abstract = True  # 只是用来继承的,不会创建这个表
 21 
 22 
 23 class User(BaseModel):
 24     '''用户表'''
 25     phone = models.CharField(verbose_name='手机号', max_length=11, unique=True)
 26     email = models.EmailField(verbose_name='邮箱', max_length=25, unique=True)
 27     password = models.CharField(verbose_name='密码', max_length=32)
 28     username = models.CharField(verbose_name='昵称', default='Python小学生', max_length=20)
 29 
 30     @staticmethod
 31     def make_password(raw_password):
 32         '''生成密码'''
 33         before_password = '%s%s' % (raw_password, settings.SECRET_KEY)  # 生成密码的算法,可以自己改
 34         after_password = tools.md5(before_password)
 35         return after_password
 36 
 37     def set_password(self, raw_password):
 38         '''设置密码'''
 39         self.password = self.make_password(raw_password)
 40 
 41     def check_password(self, raw_password):
 42         '''校验登录密码'''
 43         return self.make_password(raw_password) == self.password
 44 
 45     def __str__(self):
 46         return self.username
 47 
 48     class Meta:
 49         verbose_name = '用户表'
 50         verbose_name_plural = verbose_name
 51         db_table = 'user'
 52 
 53 class Parameter(BaseModel):#继承BaseModel
 54     '''全局参数表'''
 55     name = models.CharField(verbose_name='参数名', max_length=100, unique=True)#unique=True 唯一
 56     desc = models.CharField(verbose_name='描述', max_length=200, null=True)#null=True允许传空
 57     value = models.CharField(verbose_name='参数值', max_length=100)
 58 
 59     def __str__(self):
 60         return self.name
 61 
 62     class Meta:
 63         verbose_name = '全局参数'
 64         verbose_name_plural = verbose_name
 65         db_table = 'parameter'
 66         ordering = ['-id']  # 按照id倒排。
 67 
 68 
 69 class Project(BaseModel):
 70     '''项目表'''
 71     name = models.CharField(verbose_name='项目名', max_length=100, unique=True)
 72     desc = models.CharField(verbose_name='描述', max_length=200, null=True)
 73     host = models.CharField(verbose_name='域名', max_length=1024)
 74     user = models.ForeignKey(User, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='创建者')
 75     #on_delete=models.DO_NOTHING 当删除的时候不做任何事情 db_constraint=False 不是真正的去创建外键
 76 
 77     def __str__(self):
 78         return self.name
 79 
 80     class Meta:
 81         verbose_name = '项目表'
 82         verbose_name_plural = verbose_name
 83         db_table = 'project'
 84         ordering = ['-id']  # 按照id倒排。
 85 
 86 
 87 class Interface(BaseModel):
 88     '''接口'''
 89     name = models.CharField(verbose_name='接口名称', max_length=100, unique=True)
 90     uri = models.CharField(verbose_name='接口路径', max_length=1024)
 91     params = models.CharField(verbose_name='默认参数', max_length=2048,null=True,blank=True)
 92     headers = models.CharField(verbose_name='默认Headers', max_length=2048,null=True,blank=True)
 93     user = models.ForeignKey(User, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='创建者')
 94     project = models.ForeignKey(Project, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='归属项目')
 95 
 96     def __str__(self):
 97         return self.name
 98 
 99     class Meta:
100         verbose_name = '接口表'
101         verbose_name_plural = verbose_name
102         db_table = 'interface'
103         ordering = ['-id']  # 按照id倒排。
104 
105 
106 class Case(BaseModel):
107     '''用例表'''
108     title = models.CharField(verbose_name='用例标题', max_length=100)
109     project = models.ForeignKey(Project, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='归属项目')
110     interface = models.ForeignKey(Interface, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='接口')
111     user = models.ForeignKey(User, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='创建用户')
112     method_choice = (
113         (1, 'POST'),
114         (2, 'GET'),
115         (3, 'DELETE'),
116         (4, 'PUT'),
117     )
118     method = models.SmallIntegerField(choices=method_choice, verbose_name='请求方式')
119 
120     cache_field = models.CharField(verbose_name='缓存字段', max_length=128, null=True, blank=True)#null=True,可能为空 blank=True 可能不传
121 
122     check = models.CharField(verbose_name='校验点', max_length=512)
123     params = models.CharField(verbose_name='请求参数', max_length=2048, null=True, blank=True)
124     headers = models.CharField(verbose_name='请求头信息', max_length=2048, null=True, blank=True)
125     is_json = models.BooleanField(verbose_name='参数是否是json', default=False)
126     json = models.CharField(verbose_name='json类型参数', max_length=2048, null=True, blank=True)
127     status_choice = (
128         (1, '通过'),
129         (2, '未运行'),
130         (3, '运行中'),
131         (999, '失败')
132     )
133     status = models.SmallIntegerField(choices=status_choice, verbose_name='用例状态',
134                                       default=2)  # 记录上一次的状态 每次执行后需要更新下这个表的这个字段
135     report_batch = models.CharField(verbose_name='最后一次执行的批次号', null=True, max_length=512, blank=True)
136     def __str__(self):
137         return self.name
138 
139     class Meta:
140         verbose_name = '用例表'
141         verbose_name_plural = verbose_name
142         db_table = 'case'
143         ordering = ['-id']  # 按照id倒排
144 
145 
146 class CaseCollection(BaseModel):
147     '''用例集合'''
148     name = models.CharField(verbose_name='集合名', max_length=100, unique=True)
149     desc = models.CharField(verbose_name='描述', max_length=200, null=True)
150     user = models.ForeignKey(User, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='创建者')
151     project = models.ForeignKey(Project, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='归属项目')
152     report_batch = models.CharField(verbose_name='最后一次执行的批次号', null=True, max_length=512, blank=True)
153     status_choice = (
154         (2, '未运行'),
155         (3, '运行中'),
156         (4, '执行完毕')
157     )
158     status = models.SmallIntegerField(choices=status_choice, verbose_name='用例状态',
159                                       default=2)
160     case = models.ManyToManyField(Case,verbose_name='集合下的用例')
161 
162 
163     def __str__(self):
164         return self.name
165 
166     class Meta:
167         verbose_name = '用例集合表'
168         verbose_name_plural = verbose_name
169         db_table = 'case_collection'
170         ordering = ['-id']  # 按照id倒排
171 class Report(BaseModel):
172     '''用例报告表'''
173     url = models.CharField(verbose_name='请求URL', max_length=1024)
174     project = models.ForeignKey(Project, verbose_name='项目', on_delete=models.DO_NOTHING, db_constraint=False)
175     title = models.CharField(verbose_name='用例名称', max_length=100)
176     params = models.CharField(verbose_name='请求参数', max_length=2048)
177     response = models.CharField(verbose_name='接口返回值结果', max_length=2048)
178     case = models.ForeignKey(Case, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='结果所属用例')
179     case_collection = models.ForeignKey(CaseCollection, on_delete=models.DO_NOTHING, db_constraint=False,
180                                         verbose_name='结果所属集合', null=True)
181     batch = models.CharField(verbose_name='批次', null=True, max_length=128)  # 用于区分运行的第几批集合的用例
182     reason = models.CharField(verbose_name='失败原因', null=True, max_length=128, blank=True)
183     status_choice = (
184         (1, '通过'),
185         (999, '失败')
186     )
187     duration = models.IntegerField(verbose_name='用例耗时')
188     status = models.SmallIntegerField(choices=status_choice, verbose_name='用例结果状态')
189     user = models.ForeignKey(User, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name='运行用户')
190 
191     class Meta:
192         verbose_name = '用例报告表'
193         verbose_name_plural = verbose_name
194         db_table = 'report'
195         ordering = ['-id']
196 class CasePremise(BaseModel):
197     '''依赖用例的关系表'''
198     case = models.ForeignKey(Case, verbose_name='用例id', on_delete=models.DO_NOTHING, db_constraint=False, unique=False,related_name='case')
199     premise_case = models.ForeignKey(Case, verbose_name='被依赖用例的id', on_delete=models.DO_NOTHING, db_constraint=False,
200                                      unique=False,related_name='premise_case')
201 
202     def __str__(self):
203         return self.case
204 
205     class Meta:
206         unique_together = ('case', 'premise_case')  # 联合主键,一个case对另外一个case只能依赖一次
207         verbose_name = '依赖关系表'
208         verbose_name_plural = verbose_name
209         db_table = 'case_premise'
生成数据库:
1、makemigrations skssystem

2、migrate skssystem

3、生成结果如图:

四、数据库test——练习

  1. 在项目下创建文件model_test.py
  2. 复制如下内容到文件中model_test.py
1 import django, os
2 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'earth.settings')  # 设置django的配置文件
3 django.setup()
4 from skssystem import models

练习一、外键操作练习
  • user表增加一条内容,
  • pycharm--database 增加数据方式

然后model_test.py 内容如下

1 user_obj = models.User.objects.get(id=1)
2 data = {
3     'name':'外键联系',
4     'desc':'描述',
5     'host':'http://127.0.0.1:8022',
6     'user':user_obj
7 
8 }
9 models.Project.objects.create(**data)

运行后,project 表中有一条内容

练习二、正向查询
1 project_obj = models.Project.objects.get(id=1)
2 print(project_obj)#返回项目名称
3 print(project_obj.user.nick)

练习三、反向查询

1 u_obj = models.User.objects.get(id=1)
2 print(u_obj.project_set.all())
练习四、删除--现象:project 表数据被删除
1 # 外键删除
2 models.Project.objects.get(id=1).delete()
3 
4 # 反向删除
5 u_obj = models.User.objects.get(id=1)
6 u_obj.project_set.all().delete()
练习五、外键自关联
1、使用database 中使用sql语句插入数据

2、输入内容然后执行操

3、外键操作
#  外键自关联
models.CasePremise.objects.create(case_id=1,premise_case_id=2)

# 查询
case_obj = models.Case.objects.get(id=1) # 获取id为1 的用例信息

# CasePremise
# case_obj.case.all() ==  select * from CasePremise where case_id= 1;
qs = case_obj.case.all() # all() 返回的是一个列表的qs

# [case_id为1的CasePremise数据]

for item in qs: # qs实际是CasePremise的qs
    # item 是CasePremise 依赖数据的对象
    print(item.case.title)
    print(item.premise_case.id)

多对多
 1 # INSERT INTO `case_collection`(`id`, `is_delete`, `create_time`, `update_time`, `name`, `desc`, `report_batch`, `status`, `project_id`, `user_id`) VALUES (1, 1, '2020-02-12 22:08:04.594509', '2020-02-12 22:08:04.594617', '测试平台回归', '登录和项目的回归', 'b4a64581-5805-49d5-8991-20c34656e07b', 4, 1, 2);
 2 # 用例集合和用例是多对多的关系
 3 # A集合和B集合
 4 # A用例和B用例
 5 # A集合-- A用例和B用例
 6 # B集合-- A用例和B用例
 7 case_obj_A = models.Case.objects.get(id=1)#用例A
 8 case_obj_B = models.Case.objects.get(id=2)#用例B
 9 coll_obj_A=models.CaseCollection.objects.get(id=1)#集合A
10 print(case_obj_A,case_obj_B,coll_obj_A)
11 #通过集合中case字段创建多对多的创建
12 coll_obj_A.case.add(case_obj_A)#通过add()方法,创建多对多的映射关系
13 coll_obj_A.case.add(case_obj_B)
14 coll_obj=models.CaseCollection.objects.get(id=1)#集合A
15 coll_obj.case.add(1)#创建时通过id 的方式也可以
****case_collection_case 表格中会出现两条数据

多对多创建
1 case_obj_A = models.Case.objects.get(id=1) # 获取用例A
2 case_obj_B = models.Case.objects.get(id=2) # 获取用例B
3 coll_obj = models.CaseCollection.objects.get(id=1) # 获取集合
4 coll_obj.case.add(case_obj_B) # 通过add方法 创建多对多映射关系
5 coll_obj.case.add(case_obj_A) # 通过add方法 创建多对多映射关系
6 coll_obj.case.add(1) # 创建时 通过id创建 也可以

 


多对多--查询
1 case_obj_A = models.Case.objects.get(id=1) # 获取用例A
2 case_obj_B = models.Case.objects.get(id=2) # 获取用例B
3 coll_obj = models.CaseCollection.objects.get(id=1) # 获取集合
4 print('正向查询',case_obj_A.case.all())
5 print('反向查询',case_obj_A.casecollection_set.all())
删除--多对多的关系
1 case_obj_A = models.Case.objects.get(id=1) # 获取用例A
2 case_obj_B = models.Case.objects.get(id=2) # 获取用例B
3 coll_obj = models.CaseCollection.objects.get(id=1) # 获取集合
4 coll_obj.case.clear()  # 清除掉所有和集合有关的用例关系
5 coll_obj.case.remove(1) # 通过用例id 进行删除
6 coll_obj.case.remove(case_obj_B) # 通过用例id 进行删除

更新--多对多




1 case_obj_A = models.Case.objects.get(id=1) # 获取用例A
2 case_obj_B = models.Case.objects.get(id=2) # 获取用例B
3 coll_obj = models.CaseCollection.objects.get(id=1) # 获取集合
4 coll_obj.case.set([2])  # 将用例id为1和2的和集合建立关系
五、接口开发--登录--退出登录--全局参数
1、将example/view.py 的login 复制到sksystems/views.py 下,并将导入的内容都复制
 1 import time, django_redis,pickle
 2 from django.views import View
 3 from utils.custom_views import NbView, BaseView, PostView, GetView
 4 from utils.tools import model_to_dict
 5 from . import models, forms
 6 from utils import const
 7 from utils.custom_response import NbResponse
 8 from utils.tools import md5
 9 import json
10 
11 class LoginView(View):
12     '''登录'''
13     def post(self, request):
14         user_form_obj = forms.LoginForm(request.POST)
15         if user_form_obj.is_valid():
16             user = user_form_obj.cleaned_data['user']
17             token = '%s%s' % (user.username, time.time())
18             token = md5(token)
19             try:
20                 redis = django_redis.get_redis_connection()
21             except:
22                 raise Exception("连接不上redis,请检查redis!")
23             redis.set(const.token_prefix+token, pickle.dumps(user), const.token_expire)
24             return NbResponse(token=token, user=user.username)
25         else:
26             return NbResponse(-1, user_form_obj.error_format)
2、sksystem/urls.py 增加登录接口的路径
1 from django.urls import path
2 from . import views
3 urlpatterns = [
4     path('login', views.LoginView.as_view()),#登录
5 ]
3、sksystem 目录下创建forms.py,将exampl/forms.py的登录的内容复制到sksystem/forms.py
 1 from django.core.exceptions import ValidationError
 2 from django.db.models import Q
 3 from django.forms import ModelForm, Form
 4 from django import forms
 5 
 6 from . import models
 7 from utils.tools import ExtendForm
 8 
 9 class LoginForm(Form, ExtendForm):
10     username = forms.CharField(min_length=5, max_length=20, required=True)
11     password = forms.CharField(min_length=6, max_length=20, required=True)
12 
13     def clean(self):
14         if not self.errors:  # 校验errors里面是否有错误
15             username = self.cleaned_data['username']
16             password = self.cleaned_data['password']
17             user = models.User.objects.filter(Q(phone=username) | Q(email=username))
18             if user:
19                 user = user.first()
20                 if user.check_password(password):
21                     self.cleaned_data['user'] = user
22                     return self.cleaned_data
23                 else:
24                     self.add_error('password','密码错误')
25 
26             else:
27                 self.add_error('username', '用户不存在')
4、修改settings.py下的redis的ip和密码

  •  请求接口的过程

(1)earth/urls.py 也就是api

  (2)sksystem/urls.py 也就是login

  (3)sksystem/views.py loginview

5、用postman 请求接口

 

 退出接口

(1)sksystem/views.py

1 class LogoutView(View):
2     '''退出'''
3     def post(self, request):
4         redis = django_redis.get_redis_connection()
5         redis.delete(const.token_prefix+request.META.get('HTTP_TOKEN'))
6         return NbResponse()

  (2)sksystem/urls.py

1 path('logout', views.LogoutView.as_view()),#

(3)postman接口

 全局参数接口

 

(1)sksystem/views.py

1 1 # 全局参数的接口。
2 2 class ParameterView(NbView):
3 3     search_field = ["name"]  # 根据哪些字段来搜索
4 4     filter_field = []  # 根据哪些字段来搜索
5 5     model_class = models.Parameter  # 用哪个model类
6 6     form_class = forms.ParameterForm  # 用哪个form类

 

(3)sksystem/forms.py

1 class ParameterForm(ModelForm, ExtendForm):
2     class Meta:
3         model = models.Parameter
4         exclude = ['is_delete']

 

(4)sksystem/urls.py

1 path('parameter', views.ParameterView.as_view()),#全局操作

 

  (5)postman

 

 






posted @ 2020-02-19 18:25  洛歆陌离  阅读(166)  评论(0编辑  收藏  举报