基于Python Flask实现RESTful API服务:从架构到代码详解
本文介绍如何使用轻量级Python框架Flask构建RESTful API后端服务。文章详细解析了REST的六大特性,并通过自定义路由转换器实现URL正则匹配,动态提取资源标识与参数。结合MySQL数据库,演示了如何根据HTTP方法(GET/POST/PUT/DELETE)自动组合SQL执行参数,实现轻量级ORM逻辑。
长期使用Node.js开发后端,如今为了拓展大数据领域的技能树,Python已成为无法绕过的技术栈。因此,计划将部分成熟的项目逻辑迁移至Python进行重写,这既是为了拓宽技术视野,通过对比学习深入掌握Python特性,也是为了设定明确目标以激发持续学习的动力,确保持久投入。
项目介绍
本项目旨在利用Python语言开发一套RESTful API服务,底层数据库采用MySQL。鉴于仅负责后端微服务职能,且ORM层采用自动生成SQL的策略,最终选定轻量级的Flask作为Web框架。这一选择的初衷是针对中小规模网络应用,旨在充分利用关系型数据库的优势,以支撑功能丰富的现代互联网应用场景。
REST的六个特性:
- Client-Server(客户端-服务器):强调服务器端与客户端的职责分离。
- Stateless(无状态):要求每次客户端请求必须携带完整信息,确保每一次请求相互独立,不依赖之前的会话状态。
- Cacheable(可缓存):服务器端需明确标识哪些请求结果允许被缓存,以提升性能。
- Layered System(分层系统):规定服务器与客户端的通信必须标准化,确保服务器端的内部变更不会波及客户端。
- Uniform Interface(统一接口):要求客户端与服务器之间的交互方法保持统一和标准化。
- Code on Demand(按需执行代码):允许服务器端在特定上下文中执行或返回可执行代码/脚本(注:此为REST架构约束中最少使用的一项)。
restful api
关于RESTful API的基本概念此处不再赘述,重点阐述我们实现的协议格式规范:
[GET]/rs/user/{id}/key1/value1/key2/value2/.../keyn/valuen
[POST]/rs/user[/{id}]
[PUT]/rs/user/{id}
[DELETE]/rs/user/{id}/key1/value1/key2/value2/.../keyn/valuen
说明:
- rs代表资源标识符;
- 路径中的第二节(如user)将被解析映射为数据库中的表名;
- 执行查询时,若id参数为空或为0,则忽略该参数,视为列表查询操作;
- 执行新建和修改操作时,除了接收form表单数据外,URL中的id参数也会被合并至最终参数集合中;
- 删除操作的逻辑与查询操作类似。
让flask支持正则表达式
Flask默认的路由机制不支持正则表达式,而我们需要截取完整的URL由程序自行解析。经查阅资料,通过以下步骤即可轻松实现该功能。
- 引入werkzeug库:from werkzeug.routing import BaseConverter
- 定义自定义转换器类:
class RegexConverter(BaseConverter):
def __init__(self, map, *args):
self.map = map
self.regex = args[0]
- 注册该转换器到应用实例: app.url_map.converters['regex'] = RegexConverter
- 在路由定义中使用正则截取URL: @app.route('/rs/<regex(".*"):query_url>', methods=['PUT', 'DELETE', 'POST', 'GET'])
几点疑问:
- 正则表达式(.*)理论上应匹配除回车符外的所有字符,但在此处为何无法识别问号(?)?
- 使用request.data可以获取表单数据,为何request.form无法获取?
- 在路由定义 '/rs/<regex("."):query_url>' 后若追加反斜杠变为 '/rs/<regex("."):query_url>/',为何request.data便无法获取数据?
解析json数据
解析JSON数据本身较为简单,但我们需要对客户端提交的数据进行校验。以下提供利用异常处理机制、仅解析一次的解决方案。
def check_json_format(raw_msg):
try:
js = json.loads(raw_msg, encoding='utf-8')
except ValueError:
return False, {}
return True, js
URL解析
按照既定协议规则解析URL,提取表名,并为生成SQL组合所需的参数集合。
@app.route('/rs/<regex(".*"):query_url>', methods=['PUT', 'DELETE', 'POST', 'GET'])
def rs(query_url):
(flag, params) = check_json_format(request.data)
urls = query_url.split('/')
url_len = len(urls)
if url_len < 1 or url_len > 2 and url_len % 2 == 1:
return "The params is wrong."
ps = {}
for i, al in enumerate(urls):
if i == 0:
table = al
elif i == 1:
idd = al
elif i > 1 and i % 2 == 0:
tmp = al
else:
ps[tmp] = al
ps['table'] = table
if url_len > 1:
ps['id'] = idd
if request.method == 'POST' or request.method == 'PUT':
params = dict(params, **{'table': ps.get('table'), 'id': ps.get('id')})
if request.method == 'GET' or request.method == 'DELETE':
params = ps
return jsonify(params)
完整代码
git clone https://github.com/zhoutk/pyrest.git cd rest export FLASK_APP=index.py flask run
小结
今日利用Flask完成了Web基础架构搭建,实现了URL的正确解析、客户端提交数据的提取,以及根据不同请求方式组合所需数据的功能。希望对各位的学习有所助益,也欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









