Flask搭建api服務(wù)的實(shí)現(xiàn)步驟
Flask是一個(gè)使用 Python 編寫的輕量級(jí) Web 應(yīng)用框架,很適合個(gè)人開(kāi)發(fā),我們?cè)诖颂幾鲆粋€(gè)接口。
為方便調(diào)試,本文使用get接口方式。get接口十分簡(jiǎn)單,不需要上傳任何數(shù)據(jù),在路徑后面添加一個(gè)get方法就可以用,返回的是字符串。
本文只是Flask開(kāi)發(fā)的接口的初步文檔,從最簡(jiǎn)單的接口開(kāi)發(fā)到稍微復(fù)雜一些的接口,后續(xù)如有時(shí)間,會(huì)逐步完善,包括token鑒權(quán)、跨域認(rèn)證、藍(lán)圖應(yīng)用、日志管理等等。

第一步,首先在configs中配置數(shù)據(jù)源
configs.py
HOST = '127.0.0.1'
PORT = '5432'
DATABASE = 'runoobdb'
USERNAME = 'postgres'
PASSWORD = '*****'
# 配置主數(shù)據(jù)庫(kù)
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'
# 連接其他數(shù)據(jù)庫(kù)
SQLALCHEMY_BINDS = {
'xxxdb': 'postgresql+psycopg2://postgres:123456@localhost:5432/lincms3',
'yyydb': 'postgresql+psycopg2://postgres:123456@localhost: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()
第三步,構(gòu)造了一個(gè)flaskutils,在這里定義一些接口應(yīng)用到的公共類,比如數(shù)據(jù)轉(zhuǎn)碼,將數(shù)據(jù)集轉(zhuǎn)換為json,解析url逗號(hào)參數(shù)等等,后續(xù)將在此基礎(chǔ)上拓展功能。
flaskutils.py
import decimal
import numpy as np
import json, datetime,configparser
class DataEncoder(json.JSONEncoder):
"""數(shù)據(jù)轉(zhuǎn)碼類 """
def default(self, obj):
"""針對(duì)無(wú)法轉(zhuǎn)json的數(shù)據(jù)類型進(jìn)行轉(zhuǎn)碼
目前支持的轉(zhuǎn)碼類型 1、將Numpy的intger,floating轉(zhuǎn)為int和float
2、將Numpy的ndarray轉(zhuǎn)為list
3、將np.datetime64轉(zhuǎn)化為字符串前10位 4、將datetime.datetime轉(zhuǎn)化為"%Y-%m-%d %H:%M:%S"
5、將datetime.date轉(zhuǎn)化為"%Y-%m-%d"
6、將bytes轉(zhuǎn)化為utf-8字符串
入?yún)?
obj: 數(shù)據(jù)對(duì)象
出參:
轉(zhuǎn)化后的數(shù)據(jù)
異常:
無(wú) """
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={}):
"""根據(jù)db和sql語(yǔ)句,將結(jié)果集轉(zhuǎn)換為json格式
根據(jù)db和sql語(yǔ)句,將結(jié)果集轉(zhuǎn)換為json格式
第一步:根據(jù)cursor獲取元數(shù)據(jù),生成鍵值列表
第二步:遍歷結(jié)果集,將鍵值列表和結(jié)果集組裝成字典,加入列表
第三步:將列表通過(guò)DataEncoder進(jìn)行轉(zhuǎn)碼
入?yún)?
db: 數(shù)據(jù)庫(kù)實(shí)例.
sql: 待運(yùn)行的SQL語(yǔ)句
出參:
Json格式:
舉例: {'Serak': ('Rigel VII', 'Preparer'),
'Zim': ('Irk', 'Invader'),
'Lrrr': ('Omicron Persei 8', 'Emperor')}
異常:
無(wú) """
resultdict = []
cursor = db.session.execute(sql,params=params).cursor
resultproxy = db.session.execute(sql,params=params).fetchall()
# 獲取元數(shù)據(jù)
colname = [i[0] for i in cursor.description]
# 獲取結(jié)果集,組成字典,加入列表
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傳遞參數(shù),in傳遞參數(shù)可適用于兩種傳遞方式,逗號(hào)傳遞參數(shù)或參數(shù)傳遞
此處主要是處理,逗號(hào)傳遞參數(shù),返回為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文件構(gòu)建初始版本
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語(yǔ)句,原本想嘗試一下mybis類型的配置文件,后來(lái)決定簡(jiǎn)化;主要包括三條sql,第一條不需要傳參,第二條傳遞常規(guī)參數(shù),第三條傳遞in參數(shù),尤其是in參數(shù),基本上網(wǎng)上找到的方法都不可靠,本文算是原創(chuàng)吧。
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、構(gòu)造第一個(gè)最簡(jiǎn)單sql返回接口,不需要傳遞sql參數(shù),但需要傳遞sqlid參數(shù)
@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、構(gòu)造一個(gè)sql內(nèi)部傳參的接口,通過(guò)字典參數(shù)方式
@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、通過(guò)url進(jìn)行sql參數(shù)的傳遞。
@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、通過(guò)url進(jìn)行sql參數(shù)的傳遞,不過(guò)不傳遞in參數(shù),而是在路由函數(shù)匯總內(nèi)部指定in參數(shù)
@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、通過(guò)url進(jìn)行in參數(shù)和普通參數(shù)的傳遞,這里可以支持兩種方式,一種是&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、標(biāo)準(zhǔn)化接口響應(yīng)返回結(jié)果。
@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'] + '未傳入開(kāi)始時(shí)間'
errorflag=True
if not enddate:
retinfo['returninfo'] = retinfo['returninfo'] + '未傳入結(jié)束時(shí)間'
errorflag=True
if begindate>enddate:
retinfo['returninfo'] = retinfo['returninfo'] + '開(kāi)始時(shí)間大于結(jié)束時(shí)間'
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到此這篇關(guān)于Flask搭建api服務(wù)的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Flask搭建api服務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python3.8如何解決No module named 'numpy&apos
這篇文章主要介紹了Python3.8如何解決No module named 'numpy'報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
Python3.5內(nèi)置模塊之time與datetime模塊用法實(shí)例分析
這篇文章主要介紹了Python3.5內(nèi)置模塊之time與datetime模塊用法,結(jié)合實(shí)例形式分析了Python3.5 time與datetime模塊日期時(shí)間相關(guān)操作技巧,需要的朋友可以參考下2019-04-04
Python?excel合并居中值相同的單元格實(shí)例代碼
在工作中遇到了合并具有相同條件的單元格合并的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Python?excel合并居中值相同單元格的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
Python使用argcomplete模塊實(shí)現(xiàn)自動(dòng)補(bǔ)全
argcomplete?是一個(gè)強(qiáng)大的Python庫(kù),可以大幅改善命令行應(yīng)用程序的用戶體驗(yàn),本文主要介紹了argcomplete模塊的相關(guān)用法,感興趣的小伙伴可以了解下2023-11-11
用pickle存儲(chǔ)Python的原生對(duì)象方法
下面小編就為大家?guī)?lái)一篇用pickle存儲(chǔ)Python的原生對(duì)象方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié)
本文主要介紹了Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié),用戶發(fā)送請(qǐng)求時(shí)攜帶的參數(shù)后端需要使用,而不同的發(fā)送參數(shù)的方式對(duì)應(yīng)了不同的提取參數(shù)的方式,本文就詳細(xì)的介紹一下2021-08-08
python把一個(gè)字符串切開(kāi)的實(shí)例方法
在本篇文章里小編給大家整理的是一篇關(guān)于python把一個(gè)字符串切開(kāi)的實(shí)例方法,需要的朋友們可以學(xué)習(xí)參考下。2020-09-09

