1、介绍

Flask是由python语言编写的轻量级Web应用框架,主要应用于后端框架,处理客户端请求并返回响应。

2、demo演示

from flask import Flask

#应用实例化
app = Flask(__name__)

#装饰器,也称为路由,将URL('/’)映射到视图函数(hello_world)
@app.route('/')
def hello_world():、
	#定义的视图函数
    return 'Hello, World!'

if __name__ == '__main__':
	启动内置服务器
    app.run(host='0.0.0.0', port=5000, debug=True)

大家可在python环境下,安装flask依赖,执行上述代码,flaskf服务启动后,可直接在浏览器中输入: http://ip:5000/,进行测试。

3、Flask请求和响应

flask作为后端框架,开发者需要注意的两点,一是定义请求路由地址及方法(如GET,POST),二是获取请求数据,便于定义和实现视图函数的功能,并返回响应。

3.1 演示demo

先定义一个完整的Flask服务,路由地址和视图函数,后面修改内容,均在视图函数中的获取参数数据部分的内容

from flask import Flask,request
from gevent import pywsgi

app = Flask(__name__)
#定义路由地址
demo_url = "/demo"  # 识别

#请求方式POST
@app.route(demo_url, methods=["POST"])
def predict_router():
    #获取文件数据
    file = request.files.get('file')
    #获取文档数据
    id = request.values.get('id')
    name = request.values.get('name')
    return id

def __main(mode =True):

    if mode:
        #创建WSGI服务
        server = pywsgi.WSGIServer(('0.0.0.0', 39026), app)
        print(f"-------- 端口号 , port:{server.server_port} - ------")
        #服务持续运行
        server.serve_forever()
    else:
        #内置服务启动
        app.run(host='0.0.0.0', port=39026, debug=True)

if __name__ == "__main__":
    __main()

使用上述代码启动服务后,可使用Postman接口工具直接访问。

如上图,postman工具访问服务时,定义请求方式POST,路由地址 http://ip:port/demo,提交数据用的是body中的form-data表单数据,其中的file字段是图片文件,需在file字段后面选择file类型,id和name字段使用text类型即可。

以上完整演示了后端服务启动,前端(postman工具)接口调用的完整流程。下面将会分开讲解每一部分内容,包括,前端如何定义请求体数据,发送请求,后端如何获取请求体的数据,返回响应,最终前端接收响应。

3.2 request获取请求体数据

request对象来自于flask,是一个请求上下文对象,导入即可使用,request中保存了此次HTTP请求的一切信息。

上述代码直接使用了如下的两种方式获取数据

#获取文件
request.files.get('file')

#获取文本
request.values.get('id')

另外,对于文本数据,request中还定义了,以表单的形式获取

#获取表单数据,注意,表单数据中不包含文件,文件获取方式仍用上述方式
request.form

#获取表单数据,单个字段
request.form.get('id')
request.form.get('name')

#获取表单数据,多个值(列表形式),即同一个字段可上传两个不同的数据,获取时可用list
request.form.getlist('list')

3.3 requests发送请求

使用postman工具可直接访问服务,也可使用requests发送post请求,并在其中定义请求体的数据。

import requests

#定义请求发送的函数
def send_request(file,id):
    url = 'http://localhost:39026/demo'  # 替换成你的 Flask 应用的实际接口地址
    try:
        #请求文件,以二进制形式读取
        file = {'file': open(file,'rb')}
        
        #请求文本
        data = {"id":id}
        
        #以post方式发送请求
        response = requests.post(url, files=file,data=data)
        
        #输出响应后的状态码,200表示成功
      	if response.status_code == 200:
            print("文件上传成功!")
    except requests.exceptions.RequestException as e:
        print('请求发送失败:',e)

if __name__ == "__main__":
    id = '123'
    file = ‘替换成本机文件的路径’
    send_request(file,id)

注意:这里的requests发送请求和上面的request获取请求数据,只有一个s之差!

3.4 响应返回和接收

成功执行视图函数后,后端服务往往需要向前端返回响应,而前端则需要接收响应并作出处理。

以下是比较常见的几种返回

  1. 返回普通文本或HTML页面:
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, World!'

在这个例子中,当用户访问根路径 ‘/’ 时,服务器会返回一个显示文本消息 "Hello, World!"的html页面。

  1. 返回json数据,比较常见
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/demo')
def get_json():
    data = {'id': id,'name':name}
    #字典转换为json
    return jsonify(data)

上面字典转换为json格式,其实不转换,直接返回字典也ok了,就是不知道有什么弊端没

  1. 返回响应

比如常见的图片数据的字节流,以下代码演示了,将获取到的图片数据保存到本地,并以字节流的形式返回客户端

from flask import Flask, request, jsonify, send_file
from gevent import pywsgi

app = Flask(__name__)
#定义路由地址
demo_url = "/demo"  # 识别

#请求方式POST
@app.route(demo_url, methods=["POST"])
def predict_router():
    #获取文件
    file = request.files.get('file')
    #以文件本身名字,创建文件保存路径
    file_source = './' + file.filename
    #读取文件,以二进制形式
    comp_bytes = file.read()
    #打开要保存的文件路径
    with open(file_source, "wb") as fp:
        #将读取到的二进制文件写入保存的文件路径中
        fp.write(comp_bytes)

    #使用send_file返回图片数据
    return send_file(file_source, mimetype='image/jpg')

其中,上面的send_file()函数是 Flask 中用于发送文件的函数,可选参数mimetype,指定要发送的文件的 MIME 类型。例如,‘image/jpeg’ 表示发送 JPEG 图像文件。

执行上述服务端代码后,用postman工具请求即可,下面是采用了python脚本方式请求服务并打印服务返回内容。

import json
import requests

#定义请求发送的函数
def send_request(file,id):
    url = 'http://localhost:39026/demo'  # 替换成你的 Flask 应用的实际接口地址
    try:
        #请求文件,以二进制形式读取
        files = {'file': open(file,'rb')}
        #请求文档
        data = {"id":id}
        #以post方式发送请求
        response = requests.post(url, files=files,data=data)
        if response.status_code == 200:
            print("文件上传成功!")
            #打印返回内容的字节数据
            print(response.content)
    except requests.exceptions.RequestException as e:
        print('请求发送失败:',e)

if __name__ == "__main__":
    id = '123'
    file = '文件路径'
    send_request(file,id)

常常用response接收请求服务后的响应,其中,

  • response.status_code 是服务器返回的状态码,你可以通过它来判断请求是否成功。
  • response.content 是服务器返回的内容的字节表示,用 decode(‘utf-8’) 方法将其转换为字符串,方便阅读。
  • response.headers 是一个字典,包含了服务器返回的响应头部信息

4、特殊路由

4.1 路由重定向

from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route('/usrname')
def admin():
    if True:
        return redirect(url_for('login'))
    return 'Welcome to admin page'

@app.route('/login')
def login():
    return 'Please login first'

在登陆中,常常会遇到输入用户名和密码不符合时,直接返回登陆界面。上述例子,表示当用户访问 ‘/usrname’ 路径时,条件不满足,服务器会将其重定向到 ‘/login’ 路径。

4.2 路由拦截器

不知道大家会不会碰到这种情况,在访问某些路由之前呢,需要做个身份认证或权限许可,认证成功或许可后才允许访问这些路由,这时候就用到了路由拦截器。

路由拦截器是由装饰器来拦截请求的,以下处理前和处理后的拦截,默认是针对app服务所有的路由执行的,称为全局拦截器。


```c
from flask import Flask, request
app = Flask(__name__)

@app.before_request
def before_request():
    # 在每个请求处理前执行的内容
    return ''

@app.after_request
def after_request(response): 
    # 在每个请求处理后执行的内容
    return ''

如果想对指定的路由实现拦截,局部拦截器,可在路由拦截中设置白名单,可通行的路由

@app.before_request
def before_request():
    url = request.path  # 获取当前请求的URL
    #设置白名单,不被拦截的路由
    passUrl = ["/login", "/regist"]
    if url in passUrl:
        pass
    else:
    	#请求处理前执行的内容
    return ' '
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐