自动化测试笔记python

从零搭建接口测试框架(二)——Django接口开发

2019-05-17  本文已影响18人  小楼_987f

二. Django接口开发

在这一小节,我们将编写一些接口服务,事实上这一部分并不计入框架项目范围内,只作为测试使用,可以选择跳过不看。直接下载gitbub上的代码就能进行测试,项目包中将这部分代码放置在 IntTestDemo/extra 目录下,以示区分。
为了控制篇幅,接口文档放置在下一小节。

1. 规划

Project名称:extra
App名称:super_tble
功能简介:设计一张表格,用于记录影视剧中超能人物的基本信息(共4项:序号、姓名、联系方式、住址),实现增添人物信息,查询人物信息功能。

id(序号) name(姓名) tel(联系方式) address(地址)
1 灭霸 666666 漫威宇宙
2 星爵 233333 漫威宇宙
...... ...... ....... ......

接口简介:

接口 功能 加密验证
/super_table/add 增添人物信息 AES
/super_table/search_by_name 查询人物信息 MD5签名

2. 创建Django项目

extra/    # 根目录只是项目的容器。它的名字对Django来说无关紧要;你可以将它重命名为你喜欢的任何名字
├── extra    # extra项目的实际Python包
│   ├── __init__.py    # 一个空文件,告诉Python该目录应该被视为Python包
│   ├── settings.py    # extra项目的设置/配置
│   ├── urls.py    # 用于配置url
│   └── wsgi.py    # 兼容WSGI的Web服务器的入口,为您的项目提供服务
└── manage.py    # 一个命令行实用程序,允许您以各种方式与此Django项目进行交互

1 directory, 5 files
>>> cd extra    # 进入extra项目
>>> django-admin startapp super_table    # 执行startapp命令,创建super_table
>>> python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

April 19, 2019 - 06:15:03
Django version 2.1.7, using settings 'extra.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

复制输出的地址信息(我这里是:http://127.0.0.1:8000/)粘贴到浏览器中就可以访问啦:

成功创建Django项目.png
 32 ......
 33 INSTALLED_APPS = [
 34     'django.contrib.admin',
 35     'django.contrib.auth',
 36     'django.contrib.contenttypes',
 37     'django.contrib.sessions',
 38     'django.contrib.messages',
 39     'django.contrib.staticfiles',
 40     'super_table',    # 我们刚刚创建的App
 41 ]
 42 ......
>>> cd ../    # 进入IntTestDemo目录
>>> git add .    # 将项目改动放入暂存区
>>> git commit -m "New a Django App called super_table."    # 将暂存区的的修改提交到当前分支,m参数表示添加注释
>>> git push origin master    # 推送到远程服务器(github)

3. 数据模型(Model)

  1 from django.db import models
  2 
  3 # Create your models here.
  4 # super_table表
  5 class Super_Table(models.Model):
  6     id = models.AutoField(primary_key=True)      # 序号,自增
  7     name = models.CharField(max_length=64)      # 姓名
  8     tel = models.CharField(max_length=16)       # 联系方式
  9     address = models.CharField(max_length=200)      # 地址
>>> cd ../    # 回到上级目录,即extra目录
>>> python manage.py makemigrations super_table    # 基于当前的model创建新的迁移策略文件
Migrations for 'super_table':
  super_table/migrations/0001_initial.py
    - Create model Super_Table
>>> python manage.py migrate    # 执行数据库迁移
>>> python manage.py createsuperuser
Username (leave blank to use 'arch'): admin    # 这里创建帐号
Email address: admin@sina.com    # 这里创建邮箱
Password:     # 这里创建密码
Password (again):     # 再次确认密码
The password is too similar to the email address.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

我填写的帐号和密码都是:admin,导致执行期间出现提示信息:密码信息与email地址太相似、密码至少需要8个字符等。这个时候要强势点哈,输入y回车就可以啦。
想要用 admin 来管理我们的数据表的话,还要再编辑一下 super_table/admin.py 文件:

  1 from django.contrib import admin
  2 from super_table.models import Super_Table      # 引入Super_Table
  3 
  4 # Register your models here.
  5 class STAdmin(admin.ModelAdmin):
  6     list_display = ['id', 'name', 'tel', 'address']     # 定制Admin显示栏目
  7     search_fields = ['name']        # 启用Admin搜索栏
  8 
  9 admin.site.register(Super_Table, STAdmin)       # 完成注册

完成这一步后访问:http://127.0.0.1:8000/admin/ ,输入刚才创建的帐号密码进入admin后台管理,通过这个页面就可以直接操作 Super_Table 表的增删查改了:

Admin后台管理数据表.png

4. 开发接口

 16  from django.contrib import admin
 17 from django.urls import path
 18 from django.urls import include    # 引入新的包
 19 
 20 urlpatterns = [
 21     path('admin/', admin.site.urls),
 22     path('super_table/', include(('super_table.urls', 'super_table'),namespace='super_table')),    # 包含super_table中的url配置
 23 ]

接下来,进入 super_table 目录,创建 urls.py 文件并编辑:

  1 from django.conf.urls import url
  2 from super_table import views
  3 from django.urls import path
  4 
  5 
  6 urlpatterns = [
  7     # super_table interface:
  8     path('add/', views.add, name='add'),    # 添加人物接口路径
  9     path('search_by_name/', views.search_by_name, name='search_by_name'),    # 查询人物接口路径
 10 ]
  1 import time
  2 import json
  3 import hashlib
  4 import base64
  5 from django.http import JsonResponse
  6 from django.core.exceptions import ObjectDoesNotExist
  7 from Crypto.Cipher import AES    # 用于加密解密
  8 from super_table.models import Super_Table
  9 
 10 # 自定义的装饰器,用于MD5解密
 11 def md5_sign(func):
 12     def wrapper(request, *args, **kwargs):
 13         #获取客户端传来的验证信息,格式为:(客户端MD5签名)|(客户端时间戳)
 14         auth = request.GET.get('md5_sign', '')
 15         # 验证信息不能为空
 16         if auth == '':
 17             return JsonResponse({'status': 401, 'message': 'sign is empty'})
 18         client_md5 = auth.split('|', maxsplit=1)[0]     # 客户端传送的MD5签名
 19         client_time = auth.split('|', maxsplit=1)[1]        # 客户端时间戳
 20 
 21         now_time = time.time()      # 获取当前时间
 22         server_time = str(now_time).split('.')[0]  # 截取小数点前的时间,转化为字符串
 23 
 24         # 如果客户端请求时间与服务端手里时间超过60秒,需重新申请验证
 25         if int(server_time) - int(client_time) > 60:
 26             return JsonResponse({'status': 408, 'message': 'timeout, please try           again'})
 27 
 28         # 利用客户端传送的时间戳,重新计算MD5签名,生成服务端MD5签名 
 29         hash = hashlib.md5()
 30         sign = client_time + "wahaha"       # 签名密匙为:wahaha
 31         sign_utf8 = sign.encode(encoding='utf-8')
 32         hash.update(sign_utf8)
 33         server_md5 = hash.hexdigest()
 34 
 35         # 验证客户端MD5签名与服务端MD5签名是否相符
 36         if server_md5 != client_md5:
 37             return JsonResponse({'status': 401, 'message': 'sign check fail'})
 38         else:
 39             return func(request, *args, **kwargs)
 40 
 41     return wrapper
 42 
 43 
 44 # Create your views here.
 45 def add(request):
 46     '''
 47     接收POST请求,
 48     添加人物信息
 49     '''
 50     key = "qwertyuiopasdfgh"  # 密匙
 51     iv = b"1234567890123456"    #初始化向量
 52 
 53     # 只接受POST请求
 54     if request.method == 'POST':
 55         data = request.POST.get("data", "")
 56     else:
 57         return JsonResponse({'status': 405, 'message': 'method not allowed'})
 58 
 59 #*********************** AES解密开始 ***********************************#
 60     data = base64.urlsafe_b64decode(data)      # 反向客户端base64.                        urlsafe_b64encode()操作
 61     aes = AES.new(key, AES.MODE_CBC, iv)    # 初始化加密器
 62     data = aes.decrypt(data).decode()    # 逆向解密
 63     unpad = lambda s: s[0: - ord(s[-1])]      # 消除补位填充,填充模式:PKCS#5/PKCS7
 64     data = json.loads(unpad(data))    # 转换为字典型数据
 65 #*********************** AES解密完成 ***********************************# 
 66 
 67     name = data.get('name', '')     # 人物姓名
 68     tel = data.get('tel', '')     # 人物联系方式
 69     address = data.get('address', '')     # 人物地址
 70 
 71     # 如果name、tel、address中某项为空,则返回“10010,参数错误”
 72     if name == '' or tel == '' or address == '':
 73         return JsonResponse({'status': 400, 'message': 'parameter error'})
 74 
 75     # 如果name已经存在于数据表中,返回“10020,名字已经存在”
 76     result = Super_Table.objects.filter(name=name)
 77     if result:
 78         return JsonResponse({'status': 400, 'message': 'name already exists'})
 79 
 80     # 添加成功
 81     Super_Table.objects.create(name=name, tel=int(tel), address=address)
 82     return JsonResponse({'status': 200, 'message': 'add success'})
 83 
 84 
 85 @md5_sign    # 自定义的装饰器,用于MD5解密
 86 def search_by_name(request):
 87     '''
 88     接收GET请求,
 89     查询人物信息
 90     '''
 91     name = request.GET.get('name', '')      # 想要查询的名字
 92 
 93     # 查询栏不能为空
 94     if name == '':
 95         return JsonResponse({'status': 400, 'message': 'please input a name'})
 96     else:
 97         info = {}       # 查询成功时装载人物信息
 98 
 99         # 查询失败,姓名不存在,拋出异常
100         try:
101             result = Super_Table.objects.get(name=name)
102         except ObjectDoesNotExist:
103             return JsonResponse({'status': 204, 'message': 'result is empty!'})
104 
105         # 查询成功,装载信息到info,返回
106         else:
107             info['name'] = result.name
108             info['tel'] = result.tel
109             info['address'] = result.address
110             return JsonResponse({'status': 200, 'message': 'success', 'data': info})

 43 MIDDLEWARE = [
 44     'django.middleware.security.SecurityMiddleware',
 45     'django.contrib.sessions.middleware.SessionMiddleware',
 46     'django.middleware.common.CommonMiddleware',
 47    # 'django.middleware.csrf.CsrfViewMiddleware',
 48     'django.contrib.auth.middleware.AuthenticationMiddleware',
 49     'django.contrib.messages.middleware.MessageMiddleware',
 50     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 51 ]
>>> cd ../    # 进入IntTestDemo目录
>>> git add .    # 将项目改动放入暂存区
>>> git commit -m "super_table completed"    # 将暂存区的的修改提交到当前分支,m参数表示添加注释
>>> git push origin master    # 推送到远程服务器(github)
上一篇 下一篇

猜你喜欢

热点阅读