再遇Flask restplus

    技术2022-07-11  89

    再遇Flask restplus

    ​ “所有的道别中,我最喜欢的还是明天见。”

    ​ 前段时间写了有关蓝图的部分,今天加入新的知识restplus。这一部分的基础知识自行百度就好了,后面有机会我会上传一份资源,是对这部分知识的总结和一些我的思考。话不多扯,我们从代码出发,来讲讲这一部分的知识是怎么用的。

    1.restplus

    ​ restplus的理论和基础部分,大家可以自行百度或者下载我已经上传的资源——python学习模块.rar.

    2.目录结构

    ​ 对了这个地方有一个小细节,我们一个文件下面可能会有很多个项目文件,在项目文件运行时记得把文件设置成源目录(就是灰色变成了蓝色),方法很简单:

    3.各个模块

    app:

    #创建app from werkzeug.middleware.proxy_fix import ProxyFix from flask import Flask, request from methods_move import methods_face def create_app(): app = Flask(__name__) # handle proxy server headers # 处理代理服务器头 app.wsgi_app = ProxyFix(app.wsgi_app) app.register_blueprint(methods_face.api_v1) return app

    logger_error:

    import time import logging def logger_error(): # 创建一个logger global logger logger = logging.getLogger() logger.setLevel(logging.INFO) # Log等级总开关 # 创建一个handler,用于写入日志文件 rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time())) log_path = 'C:/Users/BBD' + '/Logs/' log_name = log_path + rq + '.log' logfile = log_name fh = logging.FileHandler(logfile, mode='w') fh.setLevel(logging.DEBUG) # 输出到file的log等级的开关 # 定义handler的输出格式 formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s") fh.setFormatter(formatter) logger.addHandler(fh)

    database:

    import time import pymysql import threading from DBUtils.PooledDB import PooledDB, SharedDBConnection def mysql_pool(): POOL = PooledDB( creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host='127.0.0.1', port=3306, user='root', password='mysql123456789', database='BASEONE', charset='utf8' ) return POOL

    methods_face:

    from flask import Flask, Blueprint from flask_restplus import Api, Resource, fields from database import mysql_pool import logger_error from flask_restplus import reqparse api_v1 = Blueprint('api', __name__) api = Api(api_v1, version='1.0', title='TodoMVC API', description='A simple TodoMVC API', ) ns = api.namespace('todos', description='TODO operations') todo = api.model('Todo', { 'id': fields.Integer(readOnly=True, description='The task unique identifier'),#整型字段 'author': fields.String(required=True),#String字段 'age': fields.Integer(required=True), 'current_address': fields.String(required=True), 'times_awards': fields.Integer(required=True) }) parser = reqparse.RequestParser(bundle_errors=True) parser.add_argument('id', type=int, required=True) parser.add_argument('author', type=str, required=True) parser.add_argument('age', type=int, required=True) parser.add_argument('current_address', type=str, required=True) parser.add_argument('times_awards', type=int, required=True) POOL = mysql_pool() @ns.route('/create_todo') class Todo(Resource): @ns.doc('create_todo') @ns.expect(todo) @ns.marshal_with(todo, code=201) def post(self): '''创建一个新的task''' # return SQL.create(api.payload), 201 # data = json.loads(api.payload) todo = {} id = todo['id'] = api.payload['id'] author = todo['author'] = api.payload['author'] age = todo['age'] = api.payload['age'] current_address = todo['current_address'] = api.payload['current_address'] times_awards = todo['times_awards'] = api.payload['times_awards'] conn = POOL.connection() cursor = conn.cursor() sql_insert = "INSERT INTO author (id,author,age,current_address,times_awards) VALUES (%s,%s,%s,%s,%s)" cursor.execute(sql_insert, (id, author, age, current_address, times_awards)) conn.commit() conn.close() return todo @ns.route('/get_todo/<int:id>') class TodoSimple(Resource): @api.doc('get_todo') @ns.marshal_with(todo) def get(self, id): '''获取id指定的todo项''' try: conn = POOL.connection() cursor = conn.cursor() sql_select = "select * from author where id = %s" if cursor.execute(sql_select, id): info = cursor.fetchall() conn.close() jsondata = [] for row in info: result = {} result["id"] = row[0] result["author"] = row[1] result["age"] = row[2] result["current_address"] = row[3] result["times_awards"] = row[4] jsondata.append(result) return jsondata else: api.abort(404, "Todo {} doesn't exist".format(id)) return todo except: logger_error() pass @ns.route('/delete_todo/<int:id>') class TodoSimple(Resource): @ns.doc('delete_todo') @ns.response(204, 'Todo deleted') def delete(self, id): '''根据id删除对应的task''' try: conn = POOL.connection() cursor = conn.cursor() sql_drop = "DELETE FROM author WHERE id = %s" cursor.execute(sql_drop, id) conn.commit() conn.close() return '', 204 except: logger_error() return '', 404 @ns.route('/update_todo/<int:id>') class TodoSimple(Resource): @ns.doc('update_todo') @ns.expect(todo) @ns.marshal_with(todo) def put(self, id): '''更新id指定的task''' try: todo = {} if id == api.payload['id']: todo['id'] = id author = todo['author'] = api.payload['author'] age = todo['age'] = api.payload['age'] current_address = todo['current_address'] = api.payload['current_address'] times_awards = todo['times_awards'] = api.payload['times_awards'] conn = POOL.connection() cursor = conn.cursor() sql_update = "UPDATE author SET author=%s,age=%s,current_address=%s,times_awards=%s WHERE id = %s" cursor.execute(sql_update, (author, age, current_address, times_awards, id)) conn.commit() conn.close() return todo except: pass logger_error() return '', 404

    运行程序——manager:

    from app import create_app flask_app = create_app() if __name__ == '__main__': flask_app.run(host='0.0.0.0', debug=True)

    4.代码结果展示

    ​ 能成功完成基本的增删改查:

    ​ 打开里面具体看看(我就列举一个啊,我懒):

    5.对模块的解释

    ​ 写这一部分是简单梳理一下部分模块的逻辑和方法,这次实例中呢,除了服务模块(methods_face)外,其他模块都比较好理解,那我们就来梳理一下这个模块吧~

    ​ 导出需要的模块:

    from flask import Flask, Blueprint from flask_restplus import Api, Resource, fields from database import mysql_pool import logger_error from flask_restplus import reqparse

    ​ 注册蓝图并设置一下需要的配置信息:

    #注册蓝图 api_v1 = Blueprint('api', __name__) #配置蓝图信息 api = Api(api_v1, version='1.0', title='TodoMVC API', description='A simple TodoMVC API', ) #设置api名字 ns = api.namespace('todos', description='TODO operations') #设置api的model的样式 todo = api.model('Todo', { 'id': fields.Integer(readOnly=True, description='The task unique identifier'),#整型字段 'author': fields.String(required=True),#String字段 'age': fields.Integer(required=True), 'current_address': fields.String(required=True), 'times_awards': fields.Integer(required=True) }) #使用一个解析器先定义好我们需要的参数,方便后面去解析这些参数 parser = reqparse.RequestParser(bundle_errors=True) parser.add_argument('id', type=int, required=True) parser.add_argument('author', type=str, required=True) parser.add_argument('age', type=int, required=True) parser.add_argument('current_address', type=str, required=True) parser.add_argument('times_awards', type=int, required=True)

    ​ 加入数据库连接池:

    POOL = mysql_pool()

    ​ 接口来了!

    @ns.route('/create_todo') class Todo(Resource): @ns.doc('create_todo') @ns.expect(todo) @ns.marshal_with(todo, code=201) def post(self): '''创建一个新的task''' # return SQL.create(api.payload), 201 # data = json.loads(api.payload) todo = {} id = todo['id'] = api.payload['id'] author = todo['author'] = api.payload['author'] age = todo['age'] = api.payload['age'] current_address = todo['current_address'] = api.payload['current_address'] times_awards = todo['times_awards'] = api.payload['times_awards'] conn = POOL.connection() cursor = conn.cursor() sql_insert = "INSERT INTO author (id,author,age,current_address,times_awards) VALUES (%s,%s,%s,%s,%s)" cursor.execute(sql_insert, (id, author, age, current_address, times_awards)) conn.commit() conn.close() return todo @ns.route('/get_todo/<int:id>') class TodoSimple(Resource): @api.doc('get_todo') @ns.marshal_with(todo) def get(self, id): '''获取id指定的todo项''' try: conn = POOL.connection() cursor = conn.cursor() sql_select = "select * from author where id = %s" if cursor.execute(sql_select, id): info = cursor.fetchall() conn.close() jsondata = [] for row in info: result = {} result["id"] = row[0] result["author"] = row[1] result["age"] = row[2] result["current_address"] = row[3] result["times_awards"] = row[4] jsondata.append(result) return jsondata else: api.abort(404, "Todo {} doesn't exist".format(id)) return todo except: logger_error() pass @ns.route('/delete_todo/<int:id>') class TodoSimple(Resource): @ns.doc('delete_todo') @ns.response(204, 'Todo deleted') def delete(self, id): '''根据id删除对应的task''' try: conn = POOL.connection() cursor = conn.cursor() sql_drop = "DELETE FROM author WHERE id = %s" cursor.execute(sql_drop, id) conn.commit() conn.close() return '', 204 except: logger_error() return '', 404 @ns.route('/update_todo/<int:id>') class TodoSimple(Resource): @ns.doc('update_todo') @ns.expect(todo) @ns.marshal_with(todo) def put(self, id): '''更新id指定的task''' try: todo = {} if id == api.payload['id']: todo['id'] = id author = todo['author'] = api.payload['author'] age = todo['age'] = api.payload['age'] current_address = todo['current_address'] = api.payload['current_address'] times_awards = todo['times_awards'] = api.payload['times_awards'] conn = POOL.connection() cursor = conn.cursor() sql_update = "UPDATE author SET author=%s,age=%s,current_address=%s,times_awards=%s WHERE id = %s" cursor.execute(sql_update, (author, age, current_address, times_awards, id)) conn.commit() conn.close() return todo except: pass logger_error() return '', 404

    注意点:

    1.api.payload来传入参数

    2.简单介绍一下swagger文档,就是@api.doc,@api.expect,@api.marshal_with,@api.route

    ​ (1)api.doc()装饰器允许您在文档中包含额外的信息

    ​ (2)expect()装饰器允许您指定预期的输入字段。它接受一个可选的布尔参数validate,该参数指示是否应该验证负载

    ​ (3)这个装饰器的工作方式类似于原始marshal_with()装饰器,不同之处在于它记录了这些方法。可选参数代码允许指定预期的HTTP状态代码(默认为200)。可选参数as_list允许您指定对象是否作为列表返回。

    ​ (4)可以使用Api.route()的doc参数提供类范围的文档。此参数接受与Api.doc()装饰器相同的值

    ​ 如果大家只是想知道怎么简单的运用,那么看我代码+这一部分的说明应该就可以,如果大家想深入了解一下原理和更高级的运行,可以去看swagger官方文档,如果大家想要中文版的,可以去下载一下我上传的"python 学习模块.rar"资源(放心,免费的,不会让你们破费的hh,给博客点个赞就成)

    6.模型的不足

    ​ flask中有很多相互包容的包,在有对应包情况下尽量避免自己去手动创建。这次实例中使用的数据库连接是我查询资料仿照连接池来写的,这一部分应该去使用和flask框架兼容性更好的sqlalchemy模块去连接数据库。

    工作方式类似于原始marshal_with()装饰器,不同之处在于它记录了这些方法。可选参数代码允许指定预期的HTTP状态代码(默认为200)。可选参数as_list允许您指定对象是否作为列表返回。

    ​ (4)可以使用Api.route()的doc参数提供类范围的文档。此参数接受与Api.doc()装饰器相同的值

    ​ 如果大家只是想知道怎么简单的运用,那么看我代码+这一部分的说明应该就可以,如果大家想深入了解一下原理和更高级的运行,可以去看swagger官方文档,如果大家想要中文版的,可以去下载一下我上传的"python 学习模块.rar"资源(放心,免费的,不会让你们破费的hh,给博客点个赞就成)

    6.模型的不足

    ​ flask中有很多相互包容的包,在有对应包情况下尽量避免自己去手动创建。这次实例中使用的数据库连接是我查询资料仿照连接池来写的,这一部分应该去使用和flask框架兼容性更好的sqlalchemy模块去连接数据库。

    写在最后:好久没写博客了 o(╥﹏╥)o ,不过没事看的人也不多,我会把pycharm项目压缩上传成资源的。我会尽快更新下一部分——flask-restplus(数据库连接基于sqlalchemy)

    Processed: 0.013, SQL: 9