Python Flask API实现方法-测试开发【提测平台】阶段小结(一)

微信搜索【大奇测试开】,关注这个坚持分享测试开发干货的家伙。

 

本篇主要是对之前几次分享的阶阶段的总结,温故而知新,况且虽然看起来是一个小模块简单的增删改查操作,但其实涉及的内容点是非常的密集的,是非常基础的,也贯穿了整个流程,后续的模块开发操作在掌握这几篇基础上会很快速,如果你还没看过之前的内容,可以参照下边往期阅读进行学习,不过这不影响单纯你想看看如何用python Flask实现常用的Resufl API。

================    往期推荐      ==================

 =============================================

Flask 一个python的web架构服务,实现前后端的开发,在本项目主要是使用它的 Resful API 实现能能力,虽说页面能力可以通过jinjia实现,但当今有更简单,好用的类似vue这样的开箱即用的开源框架,因此做到前后端分离,让它发挥好后端接口能力就好了,当然还有一些其他优秀的框架比如tornado、django、bootstrap等等,但基于接口和此项目flask更为合适。

 

现在就着分享项目来总结下Flask已经使用过的一些基础能力,以及再做一些扩展。

 

Flask程序入口

一个最小的 Flask 应用,也是程序代码的运行起点,文件名app.py

from flask import Flask

app = Flask(__name__)

@app.route("/api/sayHello/")
def hello_world():
    return "Hello, TPM!"

if __name__ == '__main__':
    app.run()

这一小段代码最简单的实现了一个默认的GET请求接口 /api/sayHello,没有请求参数,返回的是一个“Hello,TPM”字符串。

  1.  首先是引入Flask类

  2. 然后创建了该类的一个实例,该实例将成为一个Web服务器网关接口( Python Web Server Gateway Interface,缩写为 WSGI )应用

  3. 使用 装饰器 route() 来告诉 Flask 触发函数 的 URL ,默认HTTP请求方法为GET类型

  4. 被修饰的方法实现返回一个字符串,默认返回 text/htm 类型

  5. Python程序的主方法,程序执行入口(次代码中省略也可以运行)

理解上边的代码后,开启一个终端,执行方法 $ flask run 启动应用,浏览器地址输入 http://127.0.0.1:5000/  即可看到返回的字符串 “Hello,TPM!”

 

app.run() 还涉及到几个参数,扩展介绍下,如果你使用类似PyCharmm开发工具,使用command + 鼠标左键 就可以点击跳转方法的实现,方法如下,如果英文好的可以直接官方解释。

def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):

这里可以设置参数分别是host-指定IP,port-指定端口,debug-调试模式

  1. host设定

    默认的host为本地地址127.0.0.1 只能本地访问调试,如果局域网其他机器允许访问,就需要设置host=本机IP,或者host=0.0.0.0让其自行识别

  2. port设定

    默认port为5000端口,如果想用其他端口需要给定此参数如port=8082

  3. debug设定

    通过debug=True设定调试模式,这样每次有代码修改保存时程序会自动重新热加载,不需要每次重新启动。

一个简单的配置如下:

app.run(host="0.0.0.0", port=8082, debug=True)

这里需要特别注意的是,方法配置必须使用 python3 app.py 去启动程序,如果是用上述 flask run 命令或者PyCharm启动,方法里设置参数是无效的,需要通过指定参数 flask run --host=0.0.0.0 --port=8082 或者配置参数

 

  

Flask的路由和HTTP方法

路由顾名思义就是给定请求路径,在最小应用的例子中已经说过是通过route() 装饰器 设置URL,方法就是给定第一个字符串参数如“/api/project/select”,至于如何配置参数规则下边具体讲。

 

HTTP方法 在Flask框架实现【提测平台】接口项目中分别使用了GET、POST、Delete三种常用的请求方法,其实现在业界开发(不管什么语言)使用最频繁的时候GET/POST两种,基本解决所有操作。

定义接口的请求方法也很简单就是在路由内指定参数 methods=['方法']

@app.route("/api/product/search",methods=['GET'])
def product_search():
    return "GET接口请求查询产品操作"


@app.route("/api/product/create",methods=['POST'])
def product_create():
    return "POST接口请求新增产品操作"

@app.route("/api/product/delete", methods=['DELETE'])
def product_delete():
    return "Delete接口请求新增产品操作"

这些代码加在最小程序app.py重新运行后(debug=True自动重新加载),用Postman分别用对应的方法请求,都会正常返回return中的给定的字符串内容,这里可以尝试下如果一个接口设定了POST类型,如果测试用其他类型,则会返回 405 Method Not Allowed 表示不被允许的请求方法。

我们注意到methods=[]是个数组,所以我们可以对一个api指定多种类型的,比如给定GET和POST这样客户端用对应哪种方法请求都会正常返回值。

@app.route("/api/product/list",methods=['GET','POST'])
def product_list():
    return "我支持GET和POST两种"

 

Flask接口模块化

从上边的定义很多接口可以看到我们所有的定义都编写在主程序类里,这样对于稍微复杂的应用程序代码就会很臃肿,现在编程都都讲究各种模式或者分模块编程,那么教程项目中 blueprints (网络中文译为蓝图)就是这个作用,以上边的例子来优化,将所有/api/product/* 的接口全部抽出来放到一个product.py 文件中,并定义一个别名为app_product 蓝图。

from flask import Blueprint

app_product = Blueprint("app_product", __name__)

@app_product.route("/api/product/search",methods=['GET'])
def product_search():
    return "GET接口请求查询产品操作"


@app_product.route("/api/product/create",methods=['POST'])
def product_create():
    return "POST接口请求新增产品操作"

@app_product.route("/api/product/delete", methods=['DELETE'])
def product_delete():
    return "Delete接口请求新增产品操作"

@app_product.route("/api/product/list",methods=['GET','POST'])
def product_list():
    return "我支持GET和POST两种"

 

接着就要在app.py 注册blueprint,保存自动运行

from flask import Flask
# 导入模块类
from apis.products import app_product

app = Flask(__name__)
# 注册blueprint
app.register_blueprint(app_product)

@app.route("/api/sayHello/")
def hello_world():
    return "Hello, TPM!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8082, debug=True)

再次通过postman请求之前几个接口,一切正常,但看上去是不是清爽很多。

同样我们跳转blueprints.py源码查看 __init__ 方法还有不少参数,比如url_prefix="/api/product" 定义统一URL前缀,那么在 route 路径定义都可以去掉相同的前缀路径/api/product,这样更清爽了,至于其他参数后续涉及到再讲解,或者直接源代码。

 

Flask接口参数

本篇总结和扩展最后一个知识点,就是客户端传参和服务器获取参数的几种常见方式。

1)GET通过 request.args 获取params值,没有匹配的为None

from flask import request
@app_product.route("/api/product/search",methods=['GET'])
def product_search():
    # 获取?后指定的title值,没有为None
    title = request.args.get('title')

    return {'tilte':title}

运行请求测试如下:

 

 

2)POST通过 requext.form 获取form值,也可以用arg获取所有参数和指定参数,具体解释看代码注释

from flask import request

@app_product.route("/api/product/create",methods=['POST'])
def product_create():
    # 获取?后指定title=的值,取不到默认为None
    title = request.args.get('title')
    # args 获取所有URL?后边的参数和值
    args = request.args
    print(args)
    # 获取Post format格式的值(缺失会报错)
    keyCode = request.form["keyCode"]

    return {'title': title, 'keyCode': keyCode}

运行请求测试如下:

 

 

3)POST通过 request.get_data() 获取json body参数,也通过request.json.get("key")获取body内指定关键词的值。

from flask import request
@app_product.route("/api/product/update",methods=['POST'])
def product_update():
    # 获取body中某个值,取不到默认为None
    keyCode = request.json.get('keyCodes')
    print(keyCode)

    # 获取整个json字符串体
    body = request.get_data()
    print(type(body))

    return body

运行请求测试如下:

 

 

这里在扩展一个可能用到了传参方式,路径的参数形式,并可以严格限制传递的类型,方式在route path 定义<类型:关键词>,然后通过方法同关键词参数获取。

@app.route('/api/project/remove/<int:project_id>',methods=['DELETE'])
def project_remove(project_id):
    print(project_id)
    return '我是从路径获取并且只接收int类型:{}'.format(project_id)

进行delete方法请求测试结果如下

 

 

跨域问题

项目是一个前后端分离的程序,由于 浏览器同源策略 会产生跨域问题,解决的办法是前端做路由转发,或者后端服务开启可跨域,之前在前后端互通的章节讲过,这里直接贴出代码。

flask_cors *

app = Flask(__name__)
CORS(app, supports_credentials=True)

至于什么是同源策略,可以参考给出的参考文档自行扩展阅读。

相信通过之前本篇总结,再加上之前几个实战分享,flask实现接口是不是如此简单啦,下一篇将对vue前端进行一个小结。

 

【参考&拓展】

Flask中文文档:https://dormousehole.readthedocs.io/en/latest/index.html

Flask英文API文档:https://flask.palletsprojects.com/en/2.0.x/api/

浏览器同源策略:https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy

 

原创不易,经过实践的总结分享更不易,如果你觉得有用,请点击推荐,也欢迎关注我博客园和微信公众号。

posted @ 2021-08-19 09:59  MrZ大奇  阅读(575)  评论(0编辑  收藏  举报