flasklet使用指南
概述
flasklet是Flask的封装,它实现了Flask应用程序的模块化开发。有了它,RESTFUL API开发者可以按照固定的开发模式,把相似功能的API封装在一个python package里。比如,我们开发了一个wedb的包,封装了sqlalchemy,并提供RESTFUL API访问路径。要使用flasklet启用该模块,只需要运行如下命令:
python -m flasklet.flasklet -m '["wedb.restful"]' -c '{"SQLALCHEMY_DATABASE_URI":"mysql+mysqlconnector://52goadmin:************@quanklife.com:3306/52go?charset=utf8","WEDB_ROOT_URL":"/wedb"}'
注意命令选项:
-m选项后面的["wedb.restful"]指定了flasklet要装载的模块列表
-c是应用程序环境配置项,参数的每一项键值对被传入到各个模块中
以上命令告诉flasklet:
-装入wedb.restful模块
-使用mysql+mysqlconnector://52goadmin:************@quanklife.com:3306/52go连接数据库
-/wedb为API的根路径
flasklet源代码
flasklet代码可以用如下命令获取并安装:
git clone ssh://dev@quanklife.com:5010/opt/codes/52go
cd 52go
python setup.py install
flasklet帮助
使用如下命令,可获取帮助:
python -m flasklet.flasklet -h
帮助文本如下:
Usage: flasklet.py [options]
Options:
-h, --help show this help message and exit
-H HOST, --host=HOST IP address to bind.
-p PORT, --port=PORT The listen port.
-u STATIC_URL_PATH, --static-url-path=STATIC_URL_PATH
The static url path
-f STATIC_FOLDER, --static-folder=STATIC_FOLDER
The static folder.
-t TEMPLATE_FOLDER, --template-folder=TEMPLATE_FOLDER
The templates folder.
--home-page=HOME_PAGE
Home page.
-m MODULE_LIST, --module-list=MODULE_LIST
Extended routes.
-c CONFIG, --config=CONFIG
Extended routes.
-l LOGGING_LEVEL, --logging-level=LOGGING_LEVEL
Set logging level.
-C CONFIG_FILE, --config-file=CONFIG_FILE
To specify the config file including all options.
To see how to write a config file, please open the
flashlet.conf.
-h, --help 获取帮助
-H HOST, --host=HOST 指定绑定的IP地址,缺省为0.0.0.0
-p PORT, --port=PORT 指定http监听的端口
-u STATIC_URL_PATH, --static-url-path=STATIC_URL_PATH 指定静态url路径
-f STATIC_FOLDER, --static-folder=STATIC_FOLDER 指定静态文件夹
-t TEMPLATE_FOLDER, --template-folder=TEMPLATE_FOLDER 指定模板文件夹
--home-page=HOME_PAGE 指定首页
-m MODULE_LIST, --module-list=MODULE_LIST 指定模块列表,格式为'["module1","module2","module3"]'
-c CONFIG, --config=CONFIG 指定Flask运行的环境变量
-l LOGGING_LEVEL, --logging-level=LOGGING_LEVEL 指定日志级别,有DEBUG,INFO,WARNING,CRITICAL
-C CONFIG_FILE, --config-file=CONFIG_FILE 使用配置文件。如果使用配置文件,其他的选项将失效
如下是一个配置文件的例子:
#flasklet.conf
[server]
host=0.0.0.0
port=80
[route]
static_url_path=/static
static_folder=static
template_folder=templates
home_page=index.html
[module]
wefile=weos.wefile
[app]
[logging]
level=DEBUG
以上配置文件名为flasklet.conf,flasklet这样运行:
python -m flasklet.flasklet -C flasklet.conf
wefile源代码
以下是wefile.py的源代码。其中,init_flask_app是任何一个为flasklet编写的模块必须提供的函数。init_flask_app函数在flasklet中调用,传入app对象,wefile使用app对象的add_url_rule函数初始化url与函数的路由,这样,就轻松提供一个restful风格的API。
# -*- coding: utf-8 -*-
##
# @file wefile.py
# @brief Implementation of file system for restful call. Http client will call
# list_dir, walk_dir, get_file, put_file, del_file, exists functions with
# corresponding urls.
# @author Zheng Zuowu/52go
# @version 0.0.2
# @date 2019-12-23
import logging
import os
import json
from flask import request,Response
dir_root = None
##
# @brief To initialize the module for flask app.
#
# @param app The instance of flask.
#
# @return None
def init_flask_app(app):
rest_root_url = app.config['REST_ROOT_URL']
logging.debug('rest_root_url=%s'%rest_root_url)
global dir_root
dir_root = app.config['DIR_ROOT']
logging.debug('dir_root=%s'%dir_root)
app.add_url_rule(rest_root_url+'/list_dir/<path:filepath>', 'list_dir', list_dir)
app.add_url_rule(rest_root_url+'/list_dir', 'list_dir', list_dir,defaults={'filepath': ''})
app.add_url_rule(rest_root_url+'/get_file/<path:filepath>', 'get_file', get_file)
app.add_url_rule(rest_root_url+'/put_file/<path:filepath>', 'put_file', put_file, methods=['POST'])
app.add_url_rule(rest_root_url+'/del_file/<path:filepath>', 'del_file', del_file)
app.add_url_rule(rest_root_url+'/exists/<path:filepath>', 'exists', exists)
##
# @brief To list dir of the specified path. Http client will get the dir list
# by passing url 'http[s]://host/weos/list_dir/<path:filepath>'
#
# @return A dict of dir.
def list_dir(filepath):
path = dir_root + '/' + filepath
while path.find('//') >=0:
path = path.replace('//','/')
d_list = os.listdir(path)
d_dict = {}
for d in d_list:
if os.path.isdir(path+'/'+d):
d_dict[d] = {}
elif os.path.isfile(path+'/'+d):
d_dict[d] = (path+'/'+d).replace(dir_root, '').replace('//','/')
return json.dumps(d_dict)
##
# @brief For http client to download the specified file with url 'http[s]://host/weos/get_file/<path:filepath>'
#
# @param filepath The relative filepath.
#
# @return The Response object for the file content.
def get_file(filepath):
path = dir_root +'/'+ filepath
while path.find('//') >=0:
path = path.replace('//','/')
logging.debug('path=%s'%path)
try:
fp = open(path, 'rb')
content = fp.read()
return Response(content, content_type='application/octet-stream')
except FileNotFoundError as e:
logging.critical(e)
return Response(str(e).replace(dir_root, ''), status=404)
#
# @brief For http client to upload the specified file with url
# 'http[s]://host/weos/put_file/<path:filepath>'
#
# @param filepath The relative filepath.
#
# @return The Response object showing if done or not.
def put_file(filepath):
path = dir_root +'/'+ filepath
while path.find('//') >=0:
path = path.replace('//','/')
logging.debug('path=%s'%path)
try:
if os.path.exists(path):
return Response('File %s exists'%filepath, status=409)
data = request.get_data()
fp = open(path, 'wb')
fp.write(data)
fp.flush()
fp.close()
return Response('File %s uploaded.'%filepath,status=200)
except Exception as e:
if os.path.exists(path):
os.remove(path)
return Response(str(e).replace(dir_root, ''), status=404)
#
# @brief For http client to del the specified file with url
# 'http[s]://host/weos/del_file/<path:filepath>'
#
# @param filepath The relative filepath.
#
# @return The Response object showing if done or not.
def del_file(filepath):
path = dir_root +'/'+ filepath
while path.find('//') >=0:
path = path.replace('//','/')
logging.debug('path=%s'%path)
try:
os.remove(path)
return Response('File %s deleted.'%filepath,status=200)
except FileNotFoundError as e:
return Response(str(e).replace(dir_root, ''), status=404)
#
# @brief For http client to check if the specified file exists with url
# 'http[s]://host/weos/del_file/<path:filepath>'
#
# @param filepath The relative filepath.
#
# @return The Response object showing if it exists or not.
def exists(filepath):
path = dir_root +'/'+ filepath
while path.find('//') >=0:
path = path.replace('//','/')
logging.debug('path=%s'%path)
if os.path.exists(path):
return Response('File %s exists.'%filepath, status=200)
else:
return Response('File %s does not exist.'%filepath,status=404)
# EOF