Flask搭建api服務的實現步驟
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: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()
第三步,構造瞭一個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
到此這篇關於Flask搭建api服務的實現步驟的文章就介紹到這瞭,更多相關Flask搭建api服務內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- flask post獲取前端請求參數的三種方式總結
- postgresql數據庫 timescaledb 時序庫 把大數據量表轉換為超表的問題
- Python3+Flask安裝使用教程詳解
- Flask request 對象詳情
- python框架flask知識總結