Flask是Python一個很是輕量的庫,可讓你絕不費力地寫一個簡單的網站。若是你須要寫一些後臺API或者準備自動化測試數據時,Flask是一個很是不錯的選擇。html
舉個例子,咱們能夠這樣寫幾個API,具體實現暫時略過:python
# views/api.py api = Blueprint('api', __name__) @api.route('/get_todo', methods=['GET']) def get_todo(): """Get all todo tasks.""" pass @api.route('/add_todo', methods=['POST']) def add_todo(): """ Add a todo task, please post data in json format, e.g. data = { "name":"the title", "task":"the detail" } """ pass @api.route('/delete_todo', methods=['GET', 'POST']) def delete_todo(): """Delete a todo task.""" pass
一旦你的API完成,你可能須要和調用方溝通調用的細節,最好給一些例子。明明你已經在代碼裏給全部方法都寫了註釋,難道還要再把這些註釋拿出來從新組織排版一下?git
我猜你和我同樣,聽過這麼一句話。github
read the fucking manual!
但是誰會去翻代碼去看你的註釋呢,況且你的代碼他們還不必定能看到。若是能自動生成一個幫助頁面那就行了。shell
假設咱們的API都是以 http://127.0.0.1/api/*
的形式書寫的,那麼最好把API的完整列表就放在根目錄下面,好比這樣:json
view 方法的實現主要依靠 app.url_map
來獲取Flask中全部的API:flask
# views/api.py def get_api_map(): """Search API from rules, if match the pattern then we said it is API.""" for rule in get_app().url_map.iter_rules(): if re.search(r'/api/.+', str(rule)): yield str(rule), rule.endpoint @api.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('main.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)
模板的實現:api
# templates/api_index.html {% extends "./layout.html" %} {% block title %}API Root{% endblock %} {% block breadcrumb_nav %} <li><a href="{{ url_for('api.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方法,最終的展現結果會是這樣的。app
view 方法的實現思路其實也很明確,咱們能夠經過 app.view_functions
這個字典找到每一個API 的endpoint所綁定的方法,而後訪問方法的名字和文檔便可。oop
# views/main.py main = Blueprint('main', __name__) @main.route('/', methods=['GET']) def index(): """Redirect home page to docs page.""" return redirect(url_for('api.index')) @main.route('/docs/<endpoint>', methods=['GET']) def docs(endpoint): """Document page for an endpoint.""" api = { 'endpoint': endpoint, 'methods': [], 'doc': '', 'url': '', 'name': '' } try: func = get_app().view_functions[endpoint] api['name'] = _get_api_name(func) api['doc'] = _get_api_doc(func) for rule in get_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) 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!'
模板的實現:
{% extends "./layout.html" %} {% block title %}API - {{ api['name'] }}{% endblock %} {% block breadcrumb_nav %} <li><a href="{{ url_for('api.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 %}
若是你想看完整的例子,能夠到個人GitHub去拉一份代碼。
https://github.com/tobyqin/fl...
只須要三步就能夠在你的機器上運行Demo:
cd /path/to/flask_api/doc pip install -r requirements.txt python main.py
若是你以爲Demo不錯,歡迎給個Star。有建議或者想法也能夠拿來討論。
關於做者:Toby Qin, Python 技術愛好者,目前從事測試開發相關工做,轉載請註明原文出處。
歡迎關注個人博客 https://betacat.online,你能夠到個人公衆號中去當吃瓜羣衆。