【测试平台开发】——06Flask后端api开发实战(三)——API接口关联数据库
本章节演示如何创建接口服务,用接口关联数据库数据,包括get请求和post请求。
一、Flask-RESTful插件
restful api
是用于在前端与后台进行通信的一套规范。使用这个规范可以让前后端开发变得更加轻松。以下将讨论这套规范的一些设计细节。
英文地址:https://flask-restful.readthedocs.io/en/latest/
中文地址:http://www.pythondoc.com/Flask-RESTful/index.html
安装命令:
pip install flask-restful
上代码,红色字体为使用插架用法:
from flask import Flask from flask_restful import Resource, Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置数据库详细信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:1234567@localhost:8881/2022.8.3Data' # 初始化一个db db = SQLAlchemy(app) # 将flask实例加载到flask-restful api = Api(app) class TestCase(db.Model): id = db.Column(db.Integer, primary_key=True) nodeid = db.Column(db.String(80), unique=True, nullable=False) description = db.Column(db.String(120), unique=False, nullable=True) def __repr__(self): return f'<User {self.username} {self.email}>' # 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): return {'hello': 'get'} def post(self): return {'hello': 'post'} # 添加到flask-restful中,并增加路由 api.add_resource(TestCaseServer, '/') if __name__ == '__main__': # db.drop_all() # db.create_all() # # # for i in range(30): # data = TestCase(nodeid=f'nodeid_{i+1}', description=f'备注{i+1}') # db.session.add(data) # db.session.commit() app.run(debug=True)
1、GET请求
在浏览器中输入地址:http://127.0.0.1:5000/
2、POST请求
>>> import requests >>> r = requests.post("http://127.0.0.1:5000") >>> r.text '{\n "hello": "post"\n}\n'
二、接口查询数据(GET)
使用GET接口查询数据
from flask import Flask from flask_restful import Resource, Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置数据库详细信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:1234567@localhost:8881/2022.8.3Data' # 初始化一个db db = SQLAlchemy(app) # 将flask实例加载到flask-restful api = Api(app) class TestCase(db.Model): id = db.Column(db.Integer, primary_key=True) nodeid = db.Column(db.String(80), unique=True, nullable=False) description = db.Column(db.String(120), unique=False, nullable=True) def as_dict(self): """ 返回测试用例的数据 :return: """ return {"id": self.id, "nodeid": self.nodeid, "description": self.description} # 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): """ 获取所有测试用例数据 :return: """ # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases def post(self): return {'hello': 'post'} # 添加到flask-restful中,并增加路由 api.add_resource(TestCaseServer, '/testcase') if __name__ == '__main__': app.run(debug=True)
三、接口新增数据(POST)
1、首先验证使用post接口接收数据
# 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): """ 获取所有测试用例数据 :return: """ # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases def post(self): """ 新增用例 :return: """ nodeid = request.json.get("nodeid") description = request.json.get("description") return [nodeid, description] # 添加到flask-restful中,并增加路由 api.add_resource(TestCaseServer, '/testcase')
Python Console输入post请求:
>>> import requests >>> r = requests.post("http://127.0.0.1:5000/testcase", json={"nodeid": '999', "description": '999感冒灵'}) >>> r.text '[\n "999",\n "999\\u611f\\u5192\\u7075"\n]\n'
这个例子介绍post接口如何接收数据。
2、post接口结合数据库进行关联(※重点)
from flask import Flask, request from flask_restful import Resource, Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置数据库详细信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:1234567@localhost:8881/2022.8.3Data' # 初始化一个db db = SQLAlchemy(app) # 将flask实例加载到flask-restful api = Api(app) class TestCase(db.Model): id = db.Column(db.Integer, primary_key=True) nodeid = db.Column(db.String(80), unique=True, nullable=False) description = db.Column(db.String(120), unique=False, nullable=True) def as_dict(self): """ 返回测试用例的数据 :return: """ return {"id": self.id, "nodeid": self.nodeid, "description": self.description} # 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): """ 获取所有测试用例数据 :return: """ # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases def post(self): """ 新增用例 :return: """ # 把消息体中的数据,发送到数据库中 data = TestCase(**request.json) db.session.add(data) db.session.commit() return {'msg': 'OK'} # 添加到flask-restful中,并增加路由 api.add_resource(TestCaseServer, '/testcase') if __name__ == '__main__': app.run(debug=True)
Python Console输入post请求:
>>> r = requests.post("http://127.0.0.1:5000/testcase", json={"nodeid": '999', "description": '999感冒灵'}) >>> r.text # 结果 '{\n "msg": "OK"\n}\n'
数据库新增数据:
四、接口删除数据(GET)
1、首先验证使用post接口接收数据
# 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): """ (一)获取所有测试用例数据 (二)删除测试用例数据 :return: """ option = request.args.get("option") if option == 'get_testcase': # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases # 如果url中option参数值为del_testcase,代表删除用例 elif option == 'del_testcase': nodeid = request.args.get("nodeid") return nodeid
浏览器输入:http://127.0.0.1:5000/testcase?option=del_testcase&nodeid=1234
2、可以通过get接口接收数据,下一步关联数据库(※重点)
from flask import Flask, request from flask_restful import Resource, Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置数据库详细信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:1234567@localhost:8881/2022.8.3Data' # 初始化一个db db = SQLAlchemy(app) # 将flask实例加载到flask-restful api = Api(app) class TestCase(db.Model): id = db.Column(db.Integer, primary_key=True) nodeid = db.Column(db.String(80), unique=True, nullable=False) description = db.Column(db.String(120), unique=False, nullable=True) def as_dict(self): """ 返回测试用例的数据 :return: """ return {"id": self.id, "nodeid": self.nodeid, "description": self.description} # 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): """ (一)获取所有测试用例数据 (二)删除测试用例数据 :return: """ option = request.args.get("option") if option == 'get_testcase': # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases # 如果url中option参数值为del_testcase,代表删除用例 elif option == 'del_testcase': nodeid = request.args.get("nodeid") # 查询用例后进行删除 data = TestCase.query.filter_by(nodeid=nodeid).first() try: db.session.delete(data) db.session.commit() return {'msg': 'delete is ok!'} except: return {'msg': 'delete is error!'} def post(self): """ 新增用例 :return: """ data = TestCase(**request.json) db.session.add(data) db.session.commit() return {'msg': 'OK'} # 添加到flask-restful中,并增加路由 api.add_resource(TestCaseServer, '/testcase') if __name__ == '__main__': app.run(debug=True)
浏览器输入地址:http://127.0.0.1:5000/testcase?option=del_testcase&nodeid=999
数据库删除了这条数据!
3、接口批量删除数据
# 定义测试用例接口 class TestCaseServer(Resource): # get方法代表接收get请求 def get(self): """ (一)获取所有测试用例数据 (二)删除测试用例数据 :return: """ option = request.args.get("option") if option == 'get_testcase': # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases # 如果url中option参数值为del_testcase,代表删除用例 elif option == 'del_testcase': nodeid = request.args.get("nodeid") # 查询用例后进行删除 data = TestCase.query.filter_by(nodeid=nodeid).first() try: db.session.delete(data) db.session.commit() return {'msg': 'delete is ok!'} except: return {'msg': 'delete is error!'} elif option == 'del_testcases': nodeids = request.args.get("nodeids") for nodeid in nodeids.split(','): # 查询用例后进行批量删除 data = TestCase.query.filter_by(nodeid=nodeid).first() try: db.session.delete(data) except: return {'msg': 'delete is error!'} db.session.commit() return {'msg': 'delete is ok!'} api.add_resource(TestCaseServer, '/testcase')
if __name__ == '__main__':
app.run(debug=True)
浏览器输入:http://127.0.0.1:5000/testcase?option=del_testcases&nodeids=888,999
删除前:
删除后:
五、接口更新数据——API接口Url分开
为什么要分开写呢,因为如果项目足够大,不能只用一个Url写各种各样的接口,需要我们把Url区分一下,一个接口一个Url。
1、写法一
# 定义测试用例更新接口 class TestCaseUpdate(Resource): """更新测试用例""" def post(self): nodeid = request.args.get('nodeid') data = TestCase.query.filter_by(nodeid=nodeid).first() data.description = '藿香正气水' db.session.commit() return {'msg': 'update is success!'} # 添加到flask-restful中,并增加更新路由 api.add_resource(TestCaseUpdate, '/testcase/update')
Python Console输入:
>>> r = requests.post("http://127.0.0.1:5000/testcase/update?nodeid=999") >>> r.text # 结果 '{\n "msg": "update is success!"\n}\n'
2、写法二(推荐※)
# 定义测试用例更新接口 class TestCaseUpdate(Resource): """更新测试用例""" def post(self): request_body = request.json data = TestCase.query.filter_by(nodeid=request_body.get('nodeid')).first() data.description = request_body.get('description') db.session.commit() return {'msg': 'update is success!'} # 添加到flask-restful中,并增加更新路由 api.add_resource(TestCaseUpdate, '/testcase/update')
Python Console输入:
>>> r = requests.post("http://127.0.0.1:5000/testcase/update", json={'nodeid': 999, "description": '999感冒灵'}) >>> r.text # 结果 '{\n "msg": "update is success!"\n}\n'
六、整合所有API接口(重点※※※※※)
对于以上接口,全部采取Url分开的写法进行整合:
from flask import Flask, request from flask_restful import Resource, Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # 配置数据库详细信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:1234567@localhost:8881/2022.8.3Data' # 初始化一个db db = SQLAlchemy(app) # 将flask实例加载到flask-restful api = Api(app) class TestCase(db.Model): id = db.Column(db.Integer, primary_key=True) nodeid = db.Column(db.String(80), unique=True, nullable=False) description = db.Column(db.String(120), unique=False, nullable=True) def as_dict(self): """ 返回测试用例的数据 :return: """ return {"id": self.id, "nodeid": self.nodeid, "description": self.description} # 定义测试用例新增接口 class TestCaseAdd(Resource): def post(self): """ 新增用例 :return: """ data = TestCase(**request.json) db.session.add(data) db.session.commit() return {'msg': 'Add is OK!'} # 定义测试用例删除接口 class TestCaseDelete(Resource): # get方法代表接收get请求 def get(self): """ 删除测试用例数据 :return: """ if "nodeid" in request.args: nodeid = request.args.get("nodeid") # 查询用例后进行删除 data = TestCase.query.filter_by(nodeid=nodeid).first() try: db.session.delete(data) db.session.commit() return {'msg': 'delete is ok!'} except: return {'msg': 'delete is error!'} elif "nodeids" in request.args: nodeids = request.args.get("nodeids") print(nodeids) # 查询用例后进行批量删除 for nodeid in nodeids.split(','): data = TestCase.query.filter_by(nodeid=nodeid).first() try: db.session.delete(data) except: return {'msg': 'delete is error!'} db.session.commit() return {'msg': 'delete is ok!'} # 定义测试用例更新接口 class TestCaseUpdate(Resource): """更新测试用例""" def post(self): request_body = request.json data = TestCase.query.filter_by(nodeid=request_body.get('nodeid')).first() data.description = request_body.get('description') db.session.commit() return {'msg': 'update is success!'} # 定义测试用例查询接口 class TestCaseSearch(Resource): # get方法代表接收get请求 def get(self): """ (一)获取所有测试用例数据 :return: """ # 1、查找所有测试用例数据 testcase = TestCase.query.all() # 2、对测试用例进行实例化 format_test_cases = [i.as_dict() for i in testcase] return format_test_cases # 添加到flask-restful中,并增加新增路由 api.add_resource(TestCaseAdd, '/testcase/add') # 添加到flask-restful中,并增加删除路由 api.add_resource(TestCaseDelete, '/testcase/delete') # 添加到flask-restful中,并增加更新路由 api.add_resource(TestCaseUpdate, '/testcase/update') # 添加到flask-restful中,并增加查询路由 api.add_resource(TestCaseSearch, '/testcase/search') if __name__ == '__main__': # db.drop_all() # db.create_all() # # # for i in range(30): # data = TestCase(nodeid=f'nodeid_{i+1}', description=f'备注{i+1}') # db.session.add(data) # db.session.commit() app.run(debug=True)
七、说明一下接口类型
参考文章:感谢故屿γ的《Get、Put、Post、Delete 含义与区别》
1、GET 请求会向数据库发索取数据的请求,从而来获取信息,该请求就像数据库的 select 操作一样,只是用来查询一下数据,不会修改、增加数据,不会影响资源的内容,即该请求不会产生副作用。无论进行多少次操作,结果都是一样的。 2、PUT 请求是向服务器端发送数据的(与 GET 不同)从而改变信息,该请求就像数据库的 update 操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次 PUT 操作,其结果并没有不同。 3、POST 请求同 PUT 请求类似,都是向服务器端发送数据的,但是该请求会改变数据的种类等资源,就像数据库的 insert 操作一样,会创建新的内容。几乎目前所有的提交操作都是用 POST 请求的。 4、DELETE 请求顾名思义,就是用来删除某一个资源的,该请求就像数据库的 delete 操作。
就像前面所讲的一样,既然 PUT 和 POST 操作都是向服务器端发送数据的,那么两者有什么区别呢? POST 主要作用在一个集合资源之上的(url),而 PUT 主要作用在一个具体资源之上的(url/xxx),通俗一下讲就是,如 URL 可以在客户端确定,那么可使用 PUT,否则用 POST。
总结一下,Get 是向服务器发索取数据的一种请求,而 Post 是向服务器提交数据的一种请求,在 FORM(表单)中,Method默认为 “GET”,实质上,GET 和 POST 只是发送机制不同,并不是一个取一个发。
基于上面的代码,总结一下接口类型使用:
POST /url/add 新增 POST /url/update 更新 GET /url/delete 删除 GET /url/search 查询