当前位置:网站首页>Flask搭建api服务-生成API文档
Flask搭建api服务-生成API文档
2022-07-07 15:33:00 【python与大数据分析】
前面讲到了Flask实现api,但api是给别人用的,就要告诉别人如何发现api,以及api的用途、名称、出参、入参,生成api文档的做法有好多种,本文选了一种最简单的方式。
核心就是通过app.view_functions
这个字典找到每个API 的endpoint所绑定的方法,然后访问方法的名字和文档即可
从路由中搜索api,在这里可以构筑规则
def get_api_map():
"""Search API from rules, if match the pattern then we said it is API."""
for rule in app.url_map.iter_rules():
if 'docs' not in str(rule) and 'static' not in str(rule):
yield str(rule), rule.endpoint
建立两个路由,一个是api docs的首页,一个是各个api的规则定义
@app.route('/', methods=['GET'])
def index():
"""List all API to this page, api_map contains each api url + endpoint."""
api_map = sorted(list(get_api_map()))
index_url = url_for('index', _external=True)
api_map = [(index_url + x[0][1:], x[1]) for x in api_map]
return render_template('api_index.html', api_map=api_map)
@app.route('/docs/<endpoint>', methods=['GET'])def docs(endpoint):
"""Document page for an endpoint."""
api = {
'endpoint': endpoint,
'methods': [],
'doc': '',
'url': '',
'name': ''
}
try:
func = app.view_functions[endpoint]
api['name'] = _get_api_name(func)
api['doc'] = _get_api_doc(func)
for rule in app.url_map.iter_rules():
if rule.endpoint == endpoint:
api['methods'] = ','.join(rule.methods)
api['url'] = str(rule)
except:
api['doc'] = 'Invalid api endpoint: "{}"!'.format(endpoint)
return render_template('api_docs.html', api=api)
获取api的名称和api文档内容
def _get_api_name(func):
"""e.g. Convert 'do_work' to 'Do Work'"""
words = func.__name__.split('_')
words = [w.capitalize() for w in words]
return ' '.join(words)
def _get_api_doc(func):
if func.__doc__:
return func.__doc__
else:
return 'No doc found for this API!'
在原有的api函数内,补充晚上像个接口定义,包括入参、出参、名称、描述等等
@app.route('/getdimdict', methods=['GET', 'POST'])
def getdimdict():
"""
接口名称: /getdimdict 获取指标库的维度字典
接口描述:
获取指标库的维度字典,
接口入参: get方法
参数无
接口出参: json格式 data = {
"code":"200",
“info":"处理成功"
"result":{
"typecode": "datelevel\",
"typename": "\u65e5\\u671f\\u5c42\\u7ea7\",
"dimcode": "01",
"dimname": "\\u5e74\"
}
}
"""
params = {}
retinfo = {}
errorflag = False
retinfo['code'] = 200
retinfo['info'] = '处理成功'
retinfo['result'] = ''
sqltext = config[DBSECTION]['getdimdict']
jsonstr = getsqlresultjson(db, sqltext, params)
retinfo['result'] = jsonstr
response = jsonify(retinfo)
response.status_code = 200
return response
定义html的base页面-layout.html
{% extends "bootstrap/base.html" %}
{% block title %}Home{% endblock %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
{% endblock %}
{% block content %}
<div id="wrap">
<!-- Begin nav bar -->
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">API DOC DEMO</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
<!-- Begin page content -->
<div class="container">
<ul class="breadcrumb">
<li><a href="/">Home</a></li>
{% block breadcrumb_nav %}{% endblock %}
</ul>
<div class="page-header">
{% block page_header %}{% endblock %}
</div>
{% block content_area %}{% endblock %}
</div>
</div>
<div id="footer">
<div class="container">
<p class="text-muted credit">Copyright <a href="https://github.com/tobyqin/">Toby Qin</a>
- <a href="https://github.com/tobyqin/flask_api_doc">Source at Github</a></p>
</div>
</div>
{% endblock %}
api_index.html
{% extends "./layout.html" %}
{% block title %}API Root{% endblock %}
{% block breadcrumb_nav %}
<li><a href="{{ url_for('index') }}">Api Root</a></li>
{% endblock %}
{% block page_header %}
<h1>Api Root</h1>
{% endblock %}
{% block content_area %}
<pre>{
{% for i in api_map %} "<a href="/docs/{{ i[1] }}">{{ i[0] }}</a>"{{ ",\n" if not loop.last }}{% endfor %}
}</pre>
{% endblock %}
api_docs.html
{% extends "./layout.html" %}
{% block title %}API - {{ api['name'] }}{% endblock %}
{% block breadcrumb_nav %}
<li><a href="{{ url_for('index') }}">Api Root</a></li>
<li><a href="{{ api['url'] }}">{{ api['name'] }}</a></li>
{% endblock %}
{% block page_header %}
<h1>{{ api['name'] | upper }}</h1>
{% endblock %}
{% block content_area %}
<pre>
<b>Target:</b><span><a href="{{ api['url'] }}">{{ api['url'] }}</a></span>
<b>Allow :</b> <span>{{ api['methods'] }}</span>
<b>Usage :</b> <span>{{ api['doc'] }}</span>
</pre>
{% endblock %}
api首页的页面如下:
具体api的像个文档
最后,谢谢关注,谢谢支持!
边栏推荐
- LeetCode 312. 戳气球 每日一题
- Horizontal and vertical centering method and compatibility
- LeetCode 1477. Find two subarrays with sum as the target value and no overlap
- 直接上干货,100%好评
- LeetCode 152. Product maximum subarray daily question
- LeetCode 1186. Delete once to get the sub array maximum and daily question
- Binary search tree (features)
- [medical segmentation] attention Unet
- 掌握这个提升路径,面试资料分享
- Interface oriented programming
猜你喜欢
As an Android Developer programmer, Android advanced interview
The latest interview experience of Android manufacturers in 2022, Android view+handler+binder
二叉搜索树(基操篇)
作为Android开发程序员,android高级面试
Test case management tool recommendation
node:504报错
QML初学
整理几个重要的Android知识,高级Android开发面试题
Binary search tree (basic operation)
网关Gateway的介绍与使用
随机推荐
typescript ts基础知识之tsconfig.json配置选项
在哪个期货公司开期货户最安全?
Binary search tree (features)
使用JSON.stringify()去实现深拷贝,要小心哦,可能有巨坑
Cesium (4): the reason why gltf model is very dark after loading
【DesignMode】外观模式 (facade patterns)
LeetCode 403. Frog crossing the river daily
LocalStorage和SessionStorage
谈谈 SAP 系统的权限管控和事务记录功能的实现
LeetCode 1043. 分隔数组以得到最大和 每日一题
偶然升职的内心独白
LeetCode 1049. 最后一块石头的重量 II 每日一题
skimage学习(3)——使灰度滤镜适应 RGB 图像、免疫组化染色分离颜色、过滤区域最大值
如何在博客中添加Aplayer音乐播放器
正在准备面试,分享面经
LeetCode 1031. 两个非重叠子数组的最大和 每日一题
Seaborn data visualization
谎牛计数(春季每日一题 53)
LeetCode-SQL第一天
Personal notes of graphics (1)