当前位置:网站首页>Flask搭建api服务
Flask搭建api服务
2022-07-07 15:34:00 【python与大数据分析】
Flask是一个使用 Python 编写的轻量级 Web 应用框架,很适合个人开发,我们在此处做一个接口。
为方便调试,本文使用get接口方式。get接口十分简单,不需要上传任何数据,在路径后面添加一个get方法就可以用,返回的是字符串。
本文只是Flask开发的接口的初步文档,从最简单的接口开发到稍微复杂一些的接口,后续如有时间,会逐步完善,包括token鉴权、跨域认证、蓝图应用、日志管理等等。
第一步,首先在configs中配置数据源
configs.py
HOST = '127.0.0.1'
PORT = '5432'
DATABASE = 'runoobdb'
USERNAME = 'postgres'
PASSWORD = '*****'
# 配置主数据库
DB_URI = "postgresql+psycopg2://{username}:{password}@{host}:{port}/{db}".format(username=USERNAME, password=PASSWORD,
host=HOST, port=PORT, db=DATABASE)
# SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://postgres:*****@127.0.0.1:5432/runoobdb'
# 连接其他数据库
SQLALCHEMY_BINDS = {
'xxxdb': 'postgresql+psycopg2://postgres:[email protected]:5432/lincms3',
'yyydb': 'postgresql+psycopg2://postgres:[email protected]:5432/lincms4',
'zzzdb': 'sqlite:///users.db'
}
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True第二步,在exts中定义全局db
exts.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()第三步,构造了一个flaskutils,在这里定义一些接口应用到的公共类,比如数据转码,将数据集转换为json,解析url逗号参数等等,后续将在此基础上拓展功能。
flaskutils.py
import decimal
import numpy as np
import json, datetime,configparser
class DataEncoder(json.JSONEncoder):
"""数据转码类 """
def default(self, obj):
"""针对无法转json的数据类型进行转码
目前支持的转码类型 1、将Numpy的intger,floating转为int和float
2、将Numpy的ndarray转为list
3、将np.datetime64转化为字符串前10位 4、将datetime.datetime转化为"%Y-%m-%d %H:%M:%S"
5、将datetime.date转化为"%Y-%m-%d"
6、将bytes转化为utf-8字符串
入参:
obj: 数据对象
出参:
转化后的数据
异常:
无 """
if isinstance(obj, np.integer):
return int(obj)
elif isinstance(obj, np.floating):
return float(obj)
elif isinstance(obj, np.ndarray):
return obj.tolist()
elif isinstance(obj, np.datetime64):
return str(obj)[:10]
elif isinstance(obj, datetime.datetime):
return obj.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(obj, datetime.date):
return obj.strftime("%Y-%m-%d")
elif isinstance(obj, decimal.Decimal):
return float(obj)
elif isinstance(obj, bytes):
return str(obj, encoding='utf-8')
else:
return json.JSONEncoder.default(self, obj)
def getsqlresultjson(db, sql,params={}):
"""根据db和sql语句,将结果集转换为json格式
根据db和sql语句,将结果集转换为json格式
第一步:根据cursor获取元数据,生成键值列表
第二步:遍历结果集,将键值列表和结果集组装成字典,加入列表
第三步:将列表通过DataEncoder进行转码
入参:
db: 数据库实例.
sql: 待运行的SQL语句
出参:
Json格式:
举例: {'Serak': ('Rigel VII', 'Preparer'),
'Zim': ('Irk', 'Invader'),
'Lrrr': ('Omicron Persei 8', 'Emperor')}
异常:
无 """
resultdict = []
cursor = db.session.execute(sql,params=params).cursor
resultproxy = db.session.execute(sql,params=params).fetchall()
# 获取元数据
colname = [i[0] for i in cursor.description]
# 获取结果集,组成字典,加入列表
for rowproxy in resultproxy:
rowresult = dict(zip(colname, rowproxy))
resultdict.append(rowresult)
# 生成json格式
jsonstr = json.dumps(resultdict, cls=DataEncoder)
return jsonstr
def parasecommaparamtolist(param):
'''
处理in传递参数,in传递参数可适用于两种传递方式,逗号传递参数或参数传递
此处主要是处理,逗号传递参数,返回为list
# http://127.0.0.1:5000/getresultbysqlgetparaminbylist?sqlid=sql10&begindate=2018&enddate=2020&kpicode=03010101
# http://127.0.0.1:5000/getresultbysqlgetparaminbylist?sqlid=sql10&begindate=2018&enddate=2020&kpicode=03010101&kpicode=031111111
# http://127.0.0.1:5000/getresultbysqlgetparaminbylist?sqlid=sql10&begindate=2018&enddate=2020
# http://127.0.0.1:5000/getresultbysqlgetparaminbylist?sqlid=sql10&begindate=2018&enddate=2020&kpicode=03010101,222222222
# http://127.0.0.1:5000/getresultbysqlgetparaminbylist?sqlid=sql10&begindate=2018&enddate=2020&kpicode=03010101&kpicode=03010101
:param param:
:return:
字符串列表 '''
result = []
for val in param.split(','):
if val:
result.append(val)
return result第四步,在app文件构建初始版本
app.py
import configs
from exts import db
from flask import Flask
from flaskutils import *
from flask import request,jsonify
app = Flask(__name__)
# 加载配置文件
app.config.from_object(configs)
app.debug = True
db.init_app(app)
if __name__ == '__main__':
print(app.url_map)
app.run(host='0.0.0.0', port=8080)第五步,在app文件中配置sql语句,原本想尝试一下mybis类型的配置文件,后来决定简化;主要包括三条sql,第一条不需要传参,第二条传递常规参数,第三条传递in参数,尤其是in参数,基本上网上找到的方法都不可靠,本文算是原创吧。
sqldict={}
sqldict['sql1'] = """select a.*
from kpi_value a
where a.kpicode in ('01010101','02010101','03010101')
and a.datelevel='01'
and a.regionlevel='02'
"""
sqldict['sql2'] = """select a.*
from kpi_value a
where a.kpicode in ('01010101','02010101','03010101')
and a.datelevel='01'
and a.regionlevel='02'
and a.datecode>=:begindate and a.datecode<=:enddate
"""
sqldict['sql3'] = """select a.*
from kpi_value a
and a.datelevel='01'
and a.regionlevel='02'
and a.datecode>=:begindate and a.datecode<=:enddate
and a.kpicode in :kpicode
"""1、构造第一个最简单sql返回接口,不需要传递sql参数,但需要传递sqlid参数
@app.route('/getresultbysql', methods=['GET', 'POST'])
def index1():
sqlid = request.args.get('sqlid')
sqltext=sqldict[sqlid]
jsonstr = getsqlresultjson(db,sqltext)
return jsonstr, 200, {"Content-Type": "application/json"}2、构造一个sql内部传参的接口,通过字典参数方式
@app.route('/getresultbysqlparam', methods=['GET', 'POST'])
def index2():
sqlid = request.args.get('sqlid')
sqltext=sqldict[sqlid]
params = {"begindate": '2017',"enddate":'2019'}
jsonstr = getsqlresultjson(db,sqltext,params)
return jsonstr, 200, {"Content-Type": "application/json"}3、通过url进行sql参数的传递。
@app.route('/getresultbysqlgetparam', methods=['GET', 'POST'])
def index3():
sqlid = request.args.get('sqlid')
begindate = request.args.get('begindate')
enddate = request.args.get('enddate')
sqltext=sqldict[sqlid]
params = {"begindate": begindate,"enddate":enddate}
jsonstr = getsqlresultjson(db,sqltext,params)
return jsonstr, 200, {"Content-Type": "application/json"}4、通过url进行sql参数的传递,不过不传递in参数,而是在路由函数汇总内部指定in参数
@app.route('/getresultbysqlgetparamin', methods=['GET', 'POST'])
def index4():
sqlid = request.args.get('sqlid')
sqlid='sql3'
begindate = request.args.get('begindate')
enddate = request.args.get('enddate')
sqltext=sqldict[sqlid]
incond = ['01010101', '03010101']
params = {"begindate": begindate,"enddate":enddate,'kpicode':tuple(incond)}
jsonstr = getsqlresultjson(db,sqltext,params)
return jsonstr, 200, {"Content-Type": "application/json"}5、通过url进行in参数和普通参数的传递,这里可以支持两种方式,一种是&aa=xxx&aa=yyy,一种是aa=xxx,yyy。
@app.route('/getresultbysqlgetparaminbylist', methods=['GET', 'POST'])
def index5():
sqlid = request.args.get('sqlid')
sqlid='sql3'
begindate = request.args.get('begindate')
enddate = request.args.get('enddate')
incond=request.args.getlist('kpicode')
if len(incond) == 1 and ',' in incond[0]:
incond = parasecommaparamtolist(incond[0])
sqltext=sqldict[sqlid]
params = {"begindate": begindate,"enddate":enddate,'kpicode':tuple(incond)}
jsonstr = getsqlresultjson(db,sqltext,params)
return jsonstr, 200, {"Content-Type": "application/json"}6、标准化接口响应返回结果。
@app.route('/getresultbysqlgetparaminbylistresponse', methods=['GET', 'POST'])
def index6():
retinfo={}
errorflag=False
retinfo['returncode'] = 200
retinfo['returndata'] = ''
retinfo['returninfo'] = '处理成果'
sqlid = request.args.get('sqlid')
begindate = request.args.get('begindate')
enddate = request.args.get('enddate')
incond = request.args.getlist('kpicode')
if len(incond) == 1 and ',' in incond[0]:
incond = parasecommaparamtolist(incond[0])
if not incond:
retinfo['returninfo']=retinfo['returninfo'] +'未传入KPI编码'
errorflag=True
if not begindate:
retinfo['returninfo'] = retinfo['returninfo'] + '未传入开始时间'
errorflag=True
if not enddate:
retinfo['returninfo'] = retinfo['returninfo'] + '未传入结束时间'
errorflag=True
if begindate>enddate:
retinfo['returninfo'] = retinfo['returninfo'] + '开始时间大于结束时间'
errorflag=True
if errorflag==True:
retinfo['returncode'] = 400
response = jsonify(retinfo)
response.status_code = 400
return response
sqltext = sqldict[sqlid]
params = {"begindate": begindate, "enddate": enddate, 'kpicode': tuple(incond)}
jsonstr = getsqlresultjson(db, sqltext, params)
retinfo['returndata'] = jsonstr
response = jsonify(retinfo)
response.status_code = 200
return response最后,谢谢关注,谢谢支持!
边栏推荐
- 数据中台落地实施之法
- Skimage learning (3) -- adapt the gray filter to RGB images, separate colors by immunohistochemical staining, and filter the maximum value of the region
- Direct dry goods, 100% praise
- 两类更新丢失及解决办法
- [designmode] template method pattern
- 字节跳动Android金三银四解析,android面试题app
- LeetCode 1155. N ways to roll dice one question per day
- Talk about the realization of authority control and transaction record function of SAP system
- Personal notes of graphics (4)
- 一文读懂数仓中的pg_stat
猜你喜欢

水平垂直居中 方法 和兼容
作为Android开发程序员,android高级面试

Process from creation to encapsulation of custom controls in QT to toolbar (I): creation of custom controls

Test case management tool recommendation

应用在温度检测仪中的温度传感芯片

浅浅理解.net core的路由

skimage学习(3)——使灰度滤镜适应 RGB 图像、免疫组化染色分离颜色、过滤区域最大值

QT中自定义控件的创建到封装到工具栏过程(一):自定义控件的创建

【图像传感器】相关双采样CDS

Shallow understanding Net core routing
随机推荐
[designmode] flyweight pattern
Seaborn data visualization
LeetCode 1986. The minimum working time to complete the task is one question per day
【Seaborn】组合图表:FacetGrid、JointGrid、PairGrid
使用JSON.stringify()去实现深拷贝,要小心哦,可能有巨坑
LeetCode 1696. Jumping game VI daily question
Master this promotion path and share interview materials
【PHP】PHP接口继承及接口多继承原理与实现方法
Pycharm IDE下载
LeetCode 1186. 删除一次得到子数组最大和 每日一题
最新Android高级面试题汇总,Android面试题及答案
skimage学习(1)
Test case management tool recommendation
[medical segmentation] attention Unet
【Seaborn】组合图表、多子图的实现
Introduction and use of gateway
LeetCode 300. 最长递增子序列 每日一题
LeetCode 1155. 掷骰子的N种方法 每日一题
正在准备面试,分享面经
最新高频Android面试题目分享,带你一起探究Android事件分发机制