目录

  • 🍀前言
  • 🍀安装
  • 🍀导入
  • 🍀Hello World
  • 1、flask项目文件目录
  • 2、python文件内容示例
  • 🍀路由处理
  • 🍀配置
  • 1、修改app文件名,文件夹路径
  • 2、开启项目调试模式
  • 3、设置app运行的端口并开启调试
  • 🍀Request
  • 1、处理GET请求
  • 2、处理POST请求
  • 3、处理表单数据
  • 4、处理JSON数据
  • 5、处理请求头参数
  • 🍀 Response
  • 1、返回JSON数据
  • 2、设置请求头
  • 🍀Cookie
  • 🍀Session
  • 🍀Token验证
  • 1、安装并应用
  • 2、生成token
  • 3、验证token
  • 4、使用token
  • 🍀CORS跨域处理
  • 🍀返回http状态码
  • 🍀重定向
  • 🍀Restful api
  • Restful api 安装
  • Restful api 示例
  • 🍀Flask返回图片




🍀前言

官方文档:Flask Document

Flask可以搭建轻量服务api,而且使用python语言编写程序,非常方便。以前也使用过php做服务器后端,但是不喜欢php的$,而且我想多学学python,没想到Flask框架恰好能满足我的需求,简直是一个神器!特别适合我这种非计算机专业人士学习,能快速搭建api,为前端web、微信小程序等提供api服务,非常nice,爱了爱了


🍀安装

pip3 install Flask

🍀导入

from flask import Flask,request

🍀Hello World

1、flask项目文件目录

project/
    app/                    # 整个程序的包目录
        static/                 # 静态资源文件
            js/                     # JS脚本
            css/                    # 样式表
            img/                    # 图片
            favicon.ico              # 网站图标
        templates/              # 模板文件
            common/                 # 通用模板
            errors/                 # 错误页面
            user/                   # 用户模板
            posts/                  # 帖子模板
            email/                  # 邮件发送
        views/                  # 视图文件
        models/                 # 数据模型
        libs/                   #工具类
            framework/          #全局性的工具
            utils/              #小工具
        extensions/             # 各种扩展
        forms/                  # 表单文件
        main.py                # 邮件发送
    migrations/             # 数据库迁移目录
    tests/                  # 测试单元
    venv/                   # 虚拟环境
    requirements.txt        # 依赖包的列表
    config.py               # 配置文件
    manage.py               # 项目启动控制文件

2、python文件内容示例

from flask import Flask
 
app = Flask(__name__) # 实例化类flask
 
@app.route('/')
def hello_world():
    return 'Hello World!'
 
if __name__ == '__main__':
    app.run() # 默认运行在5000端口

🍀路由处理

flask支持三种路由处理
一种就是如上所展示的@app.route('/')里写路径,紧接着写函数,
还有一种使用flask.add_url_rule()方法添加

def index():
    ...

app.add_url_rule("/", view_func=index)

第三种是把不同的URL映射到同一个函数里,就是在函数前用多个@app.route(' ')

🍀配置

1、修改app文件名,文件夹路径

在app实例化的时候设置

app = Flask("my-app", static_folder="path1", template_folder="path2")

2、开启项目调试模式

app.run(debug=True)

3、设置app运行的端口并开启调试

注意:如果在开发环境中debug,要在app.run前加上

app.env="development"

否则,会出现WARNING: This is a development server. Do not use it in a production deployment.

app.run(host='0.0.0.0', port=80, debug=True)

🍀Request

flask中的request类专门用于对请求的参数进行处理,比如获得get请求参数,获得post请求参数。

必须要导入flask的request,这里导入的是全局变量(全局变量写代码量少,快速方便)

from flask import request

常用属性:

属性

描述

method

请求方法,比如POST、GET。值为字符串,有“GET”,“POST”等

form

处理POST和PUT请求

args

处理GET参数

cookies

请求的cookies,类型是dict。

headers

请求头,字典类型。

data

包含了请求的数据,并转换为字符串,除非是一个Flask无法处理的mimetype。

files

MultiDict,带有通过POST或PUT请求上传的文件。

path

获取请求文件路径:/myapplication/page.html

url_root

获取域名:http://www.baidu.com/

base_url

获取基本url:http://www.baidu.com/myapplication/page.html

url

获取全部url:http://www.baidu.com/myapplication/page.html?id=1&edit=edit

json

如果mimetype是application/json,这个参数将会解析JSON数据,如果不是则返回None。

stream

处理流

remote_addr

获取请求ip

1、处理GET请求

request.args.__str__() :列出所有参数
request.args.get('') :取出指定参数的第一个参数(如果有好多的话)
request.args.getlist('') :取出指定参数列表


2、处理POST请求

request.form.get("")

3、处理表单数据

@app.route('/api',methods=['GET','POST']) 
def api():
    #以下两行是展示form中处理文件以外的所有item
    # for item in request.form:
    #     print(item)
    d1 = request.form.get("l1")
    d2 = request.form.get("l2")
    d3 = request.form.get("l3")
    file = request.files.get('file') 
    print(file)
 	dict = {"code":"200","data":"处理完毕"}
    return jsonify(dict)

4、处理JSON数据

request.json # 返回的是dict类型

5、处理请求头参数

request.headers可以返回请求头参数。但是注意这是werkzeug.datastructures.EnvironHeaders对象。
想获取请求头的参数需要用get()方法:

request.headers.get("Host")

🍀 Response

flask接收到请求(request)后进行处理,处理完毕后会想客户端发送响应(response
flask的Response类是专门用于处理响应模块的。
使用导入两个:

from flask import make_response,Response

@app.route("/test")
def test():
    response = Response("返回信息")
    # 或者这样:response = make_response('返回信息', 200, {"header1": "header1_info"})
    response.status_code = 200
    return response

返回response最精简(懒人)模式:

return "index.html", 200, {"header1":"header1_info", "header2": "header2_info"}
# 第一个参数是返回的信息,第二个是状态码,第三个是设置请求头(字典形式)。后两个参数可以省略

补充:原则上我们返回(return)都应该是返回Response对象,但是上面的方式也是可以的,flask智能地将他们转为了Response对象。

常用属性:

属性

描述

headers

设置请求头信息

status

String类型的数据,格式为这种:“200 ok”

status_code

int 类型,就是状态码,但是不能是自定义的状态码

data

需要返回到前端的数据

set_cookie

设置cookie 的值

del_cookie

删除cookie ,不会立马删除cookie 值,会将过期时间设置为当前时间

构造函数: class flask.Response(response=None, status=None, headers=None, mimetype=None, content_type=None,direct_passthrough=False)

1、返回JSON数据

方案一 (返回JSON对象,并设置请求头)

from flask import Response
return Response(json.dumps(text),  mimetype='application/json')

方案二(使用jsonify)

from flask import jsonify
return jsonify(text)

2、设置请求头

方案一:

@app.route("/test")
def test():
    rp = Response("返回信息")
    rp.headers['header1'] = "header1_info" # 设置响应头
	rp.headers['header2'] = "header2_info" # 设置响应头
    return rp

方案二:

return "返回信息", 200, {"header1":"header1_info", "header2": "header2_info"}

方案三

return "返回信息", 200, [("header1", "header1_info"), ("header2", "header2_info")] # 使用元组的方式设

🍀Cookie

读取cookie

name=request.cookies.get('Name')
return name

设置Cookie并返回

response.set_cookie('key','value',expires=None, path='/')
return response

expires设置时间,其中expires的格式:[str, datetime.datetime, int, float]


🍀Session

session本质上还是cookie,但是时效短。flask会发送session-id给客户端(数据临时存储在服务端),客户端只要不关闭浏览器,打开多个页面浏览器会自动发送session-id,服务端能读取id来处理数据。
session能够运行在服务器端并存储交互状态。Flask中的Session与其他的Web框架不同,它使用了密钥签名的方式进行了加密。

配置SECRET_KEY:

app.config["SECRET_KEY"]='XXXXX' # 密钥是24位字符串。可以使用os.urandom(24)来生成随机字符串

session操作:

from flask import session

session["key"]= ... # 设置session,也可以不赋值来返回值,无值会异常
session.get("key") # 如果没有key值,会返回NONE
# 删除session
session.pop('key')
# 清除所有session
session.clear

🍀Token验证

token验证技术的其中一种解决方案是JSON Web Token。这是目前最常用的token认证解决方法。关于JWT的解释可以看这篇文章:基于 Token 的身份验证:JSON Web Token flask框架实现JWT token验证有好几个库,比如pyjwt,flask-jwt。我选择pyjwt,他的文档比较好。

1、安装并应用

pip install pyjwt
import jwt

2、生成token

auth = HTTPBasicAuth()
# 密钥,可随意修改
SECRET_KEY = 'abcdefghijklmm'
# 生成token, 有效时间为600min
encoded = jwt.encode({"some": "payload"}, SECRET_KEY, algorithm="HS256")
def createToken():
	payload = {"id": "此token指向的用户id", "iss": “crayonxin”,"nbf": time.time(), "exp": time.time()+604800}
	encoded = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
	rp = Response(encoded)
    rp.set_cookie("token", encoded, expires=time.time()+604800)
    rp.headers["token"] = encoded
    return rp

我设置了过期时间为604800秒(一周的时间)。
我把token放到了cookie和自定义请求头token中。我放到cookie中是为了做web时好自动存储,省事。

3、验证token

我自己封装了一个类,方便后期。

# 密钥,可随意修改
SECRET_KEY = 'abcdefghijklmm'
class Verify(object):
    def __init__(self, key, headers: werkzeug.datastructures.EnvironHeaders):  # hearders是请求头
        self.headers = headers
        self.key = key

    def verifyToken(self):
        encoded = self.headers.get("token")
        try:
            jwt.decode(encoded, self.key, issuer="crayonxin", algorithms="HS256")
        except Exception as e:

            return False
        return True
        
    # 有没有错误都会返回信息
    def DecodeToken(self):
        encoded = self.headers.get("token")
        if encoded == None:
            return "请求头没有token参数"
        try:
            dict = jwt.decode(encoded, self.key,issuer="crayonxin", algorithms="HS256")
        except jwt.ExpiredSignatureError:  # 时间到期错误
            return "时间到期"
        except jwt.InvalidSignatureError:  # token验证失败
            return "token验证失败"
        except jwt.InvalidIssuerError:  # 颁发者错误
            return "颁发者错误"
        return dict

4、使用token

def get():
	verify = Verify(SECRET_KEY, request.headers)
	if verify.verifyToken():
		print("成功")
		# 这里写验证成功的程序
		pass
	else:
		# 这里写验证失败的程序
		print("失败")
		pass
	dict = verify.DecodeToken()
	return dict

🍀CORS跨域处理

from flask_cors import * # 没有库请安装
app = Flask("name")
CORS(app,methods=["GET","POST","PUT","PATCH","DELETE","OPTIONS"], supports_credentials=True,expose_headers=['Content-Disposition'],) # 解决跨域问题

CORS类的参数:

参数名

类型

Head字段

解释

resources

字典、迭代器或字符串


全局配置允许跨域的API接口

origins

列表、字符串或正则表达式

Access-Control-Allow-Origin

配置允许跨域访问的源,*表示全部允许

methods

列表、字符串

Access-Control-Allow-Methods

配置跨域支持的请求方式,如:GET、POST

expose_headers

列表、字符串

Access-Control-Expose-Headers

自定义请求响应的Head信息,设置值之后,前端js能获取到响应头

allow_headers

列表、字符串或正则表达式

Access-Control-Request-Headers

配置允许跨域的请求头

supports_credentials

布尔值

Access-Control-Allow-Credentials

是否允许请求发送cookie


🍀返回http状态码

return “错误信息”,404

或者使用abort()

from flask import abort
abort(404)

🍀重定向

from flask import redirect

@app.route('')
def index():
	return redirect(location='',code=302)

🍀Restful api

flask不用其他的扩展其实可以构建简单的api,但是写的多的时候,看起来很乱。

有一个非常好用的库叫flask_restful,这可以非常简单的部署api服务。

flask_restful官方文档

restful api 不是技术,准确的说是一种规范。可以看这个介绍RESTful API接口设计标准及规范 一个链接代表一个资源,使用[GET][POST][PUT][DELETE][PATCH]来对资源进行处理。

Restful api 安装

pip install flask-restful

Restful api 示例

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}
    def post(self):
     	return {'':''}
    def delete(self, todo_id):
        del todo_id
        return '', 204
    def put(self,param):
    	return {}

api.add_resource(HelloWorld, '/')

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

注意: 没有flask_restful这个工具的话,以前发送JSON需要使用Reponse类或者jsonify,现在直接返回字典,自动转换成JSON格式返回,太方便了!!!


🍀Flask返回图片

flask如果想返回图片,通用的处理方式是使用Base64编码,web接收到信息,使用html的img标签即可展示图片。
下面以使用matplot绘制图为例,展示flask返回图片

import base64
from io import BytesIO
from flask import Flask
from matplotlib.figure import Figure 

app = Flask(__name__)

@app.route("/")
def hello():
    # 建立图板,不要用pyplot,会造成内存溢出
    fig = Figure()
    ax = fig.subplots()
    ax.plot([1, 2])
    # matplot图保存在io流
    buf = BytesIO()
    fig.savefig(buf, format="png")
    # io流转为base64编码的字符串
    data = base64.b64encode(buf.getbuffer()).decode("ascii")
    return f"data:image/png;base64,{data}" # 返回图片字符串,html中img标签可以直接引用该字符串。