Flask学习笔记
flask简介
轻量级web开发框架,依赖jinja2(路由模块)和 Werkzeug WSGI(模版引擎) 服务的一个微型框架。
需要使用其他功能时需要装其他插件。
初识Flask
安装flask
pip install flask
入门-简单的使用demo
# 1.导入模块Flask类
from flask import Flask
#2.建立Flask的实例,__name__ 为了找到资源
app = Flask(__name__)
#3.装饰器,为函数指定路由即访问路径
@app.route("/")
def hello_world():
    return "欢迎使用flask"
运行flask web服务:
方法一:使用bash命令(windows使用cmd命令)
#bash命令(需要先进入执行文件的目录):
export FLASK_APP=b-flask-demo  #(脚本.py的文件名)
flask run
方法二:在python代码中插入代码
if __name__ == '__main__':
    app.run()   # app 是前面是实例化Flask()的对象
然后运行文件即可,右键run即可运行,在下方终端terminal能看到如下消息说明运行成功
 * Serving Flask app "b-flask-请求方法" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
此时,浏览器输入 http://127.0.0.1:5000/ 即可访问
接口与路由技术
什么是路由?
路由简单的说就是将url 路径与 一个函数建立对应的映射关系,在输入url后,会在路由表中查询url与函数的对应关系从而调用对应的函数。
以使用bing搜说iphone为例,搜说的完整url如下:
- https: 使用的协议是https协议
- cn.bing.com: 主机(host)的域名,在向域名解析服务器dns求情后会转换为ip地址
- /search: 路由,请求的接口,通常通过不同的接口调用不同的函数
- ?q=iphone : 请求的参数
PS: 通常在主机后面还有端口如: http:127.0.0.1:5000/ 其中5000即是端口,一般http协议使用80端口,https协议使用443端口,浏览器会自动给我门填充,因此浏览器访问使用https/http 协议可以不写端口,写的话也可以哦
通过上诉介绍大致了解了什么是 路由,即域名活着ip后面 紧紧跟着的即是路由。访问对应的url时会调用对应的方法。
在flask中使用app.route()来设置路由与函数的对应关系
举例:
@app.route("/get_info/")
def welcome():
    return "正在调用的是welcome 函数"
在浏览器中输入127.0.0.1:5000/get_info 进行浏览时会返回
“正在调用的是welcome 函数”, 说明get_info调用的便是 welcome() 函数
其中127.0.0.1:5000 是flask默认的主机和端口号,在启动服务器配置 中有介绍
注意: 在浏览器中 会自动在url中补充 ‘/’,因此如果在路由中没有配置’/'有可能会返回404,找不到资源
此时在浏览器中输入 127.0.0.1:50000/get_info 会报错找不大资源,引因为 浏览器自动路径加了 ‘/’
因此定义路由时可以将’/'加上
http请求方法
常用的请求方法及使用
常见的http请求有以下四种:
- get :获取服务器资源
- post:新增服务器资源
- put:更新服务器资源
- delete:删除服务器资源
具体使用:
-  get请求: @app.route("/", methods=['get', "delete"]) def welcome(): logger.info("welcome") return {"code": 0, "msg": "get success"}
-  post请求 # post方法 @app.route("/login/", methods=['post']) def login(): logger.info("login") return {"code": 0, "msg": "post success"}可以使用postman 发送一个post请求,报文如下如下: POST /login/ HTTP/1.1 
 Host: 127.0.0.1:5000
 Content-Type: application/json
 Cache-Control: no-cache
 Postman-Token: 52bfac5c-d82e-4b5f-a12a-6c8456c3444c{ 
 “name”:“aaa”
 }发送后的收到如下响应: { "code": 0, "msg": "post success" }
-  put请求 python代码 # put方法 @app.route("/update/<name>", methods=["put"]) def update_case(name): logger.info(f"姓名修改为:{name}") return {"code": 0, "msg": f"{name } update success"}postman发送如下请求: PUT /update/lisi HTTP/1.1 Host: 127.0.0.1:5000 Content-Type: application/json Cache-Control: no-cache Postman-Token: 72f93571-965e-43de-84e8-dcf35af74517 { "name":"aaa" }postman接收响应 { "code": 0, "msg": "lisi update success" }
-  delete请求 # delete方法 @app.route("/del/<string:name>", methods=["delete"]) def delete_user(name): return {"code": 0, "msg": f"{name} delete success"}postman发送测试报文 DELETE /del/lisi HTTP/1.1 Host: 127.0.0.1:5000 Content-Type: application/json Cache-Control: no-cache Postman-Token: 9c91e7c0-518c-45e4-8ef2-7992f95728ad { "name":"aaa" }返回的响应 { "code": 0, "msg": "lisi delete success" }
处理请求的数据
在flask框架中 处理请求通常使用 flask的request库,因此第一步需要导入request
from flask import request
request的常用属性和方法:
| 属性/方法 | 说明 | 
|---|---|
| args | 记录请求中的查询参数 | 
| json | 记录请求中的 json 数据 | 
| files | 记录请求上传的文件 | 
| form | 记录请求中的表单数据 | 
| method | 记录请求使用的 HTTP 方法 | 
| url | 记录请求的 URL 地址 | 
| host | 记录请求的域名 | 
| headers | 记录请求的头信息 | 
处理get请求中的url参数
# 处理get请求的数据
# 浏览器中输入url:http://127.0.0.1:5000/login/?name=lili
@app.route("/login/", methods=["get"])
def get_data():
    print(request.args)
    args = request.args
    # 获取url中的 name 请求参数
    name = request.args.get("name")
    return {"code": 0, "msg": f"{name} login success"}
浏览器返回:
{
  "code": 0, 
  "msg": "lili login success"
}
请求参数为json格式
@app.route("/add",methods=["post"])
def add_user():
    # request.json  获取请求的json数据
    data = request.json.get("name")
    logger.info(data)
    return {"code": 0, "msg": f"{data} login success"}
表单请求
登陆网站有时候用户名和密码,前端会向后端提供一个form表单
处理方法:(ps:request 从flask中导入)
request.form
# 处理form表单
@app.route("/regist",methods=['post'])
def regist():
    form_data = request.form
    name = form_data.get("name")
    return {"code": 0, "msg:": f"{name} regist success"}
postman调试
POST /regist HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
cache-control: no-cache
Postman-Token: bb6f7dca-04a5-4cd7-8aa2-442db43742cf
Content-Disposition: form-data; name="name"
李雷
结果:
{
    "code": 0,
    "msg:": "李雷 regist success"
}
文件请求
用于前端传递图片之类的文件到后端服务器
处理方法:
- request.files.get(‘file’) 获取文件对象
- filename 获取文件名
- save() 方法保存文件到指定路径
举例:
# 处理文件
@app.route('/file', methods=['post'])
def save_file():
    # 获取文件对象
    file_obj = request.files.get('file')
    # 获取文件对象的文件名
    file_name = file_obj.filename
    # 保存文件到当前目录下
    file_obj.save(f"./{file_name}")
    logger.info(f"收到文件 {file_name}")
    return {"code": 0, "msg:": f"{file_name} rec success"}
写一个脚本测试发送文件
def test_fle():
    url = 'http://127.0.0.1:5000/file'
    # 一般打开文件都是rb二进制打开
    file = {'file': open('/Users/yang/Pictures/截图.png', 'rb')}
    r = requests.post(url,files=file)
    print(r.json())
    assert r.status_code == 200
postman也可以,但是需要使用form表单,然后选择file,
POST /file HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
cache-control: no-cache
Postman-Token: 0761192e-664e-4d79-8705-ce59d2fb45ea
Content-Disposition: form-data; name="file"; filename="/Users/yang/Pictures/截图.png
处理响应数据
常见的响应有:
返回文本
@app.route('/text')
def get_text():
	return '返回文本'
返回元组
- (response,status)
- (response,headers)
- (response,status,headers
# 返回元组
# - (response,status)
# - (response,headers)
# - (response,status,headers)
@app.route("/tuple")
def tuple_rtn():
    # 返回体body为: "code": "0", "msg":"tuple success"}
    # 返回的状态码为:900 ,一般成功是200,这里测试
    # 返回的header中 token为123456
    return '{"code": "0", "msg":"tuple success"}', 900, {"token": "123456"}
返回json 最常见、重要
-  直接返回dict() 会转换为json # 返回json 使用返回字典 @app.route("/json/") def json_rtn(): return {"status": 0, "msg": "return json success"}
-  使用jsonify(),通过键值对参数传入 # 返回json 使用返回字典 @app.route("/jsonify/") def jsonify_rtn(): return jsonify(status=1, msg="return josnify success")
返回html
- 使用模版渲染技术
- html文档必须在统计目录的templates目录下(PS:不要拼写错了)
如下目录所示:执行的.py文件与templates 在同级目录下,需要返回的html文档放到templates中
├── d-flask-处理响应.py
├── templates
│   └── hello.html
# d-flask-处理响应.py文件中
# 返回html
@app.route('/get_html/')
def html_rtn():
    return render_template('hello.html')
html文件
<html>
  <body>
    <p>
    <h1>
      这是一个一集标题
    </h1>
    这是一个html
    </p>
  </body>
</html>
设置额外的数据
使用make_response()可以添加更多的响应信息
- 设置cookie
- 设置响应头信息等
# 设置额外的返回,如返回header中的其他信息
# 设置cookie等
@app.route('/more/')
def more_rtn():
    resp = make_response(render_template('hello.html'))
    # 设置cookie
    resp.set_cookie('cookie', 'dadasda')
    # 设置响应头信息
    resp.headers["hosdaas"] = "dsad"
    return resp
启动服务配置
监听的主机
设置host参数
- 127.0.0.1 只可以本机访问
- 0.0.0.0 服务可以发布到局域网,其他电脑(同一个局域网)访问时输入服务器的ip和端口可以访问
app.run(host="0.0.0.0")
监听的端口
if __name__ == '__main__':
    app.run(host="0.0.0.0",port=10000)
debug模式
设置debug=True(默认为production)
- 实现热加载
- 开发调试更为方便
if __name__ == '__main__':
    app.run(host="0.0.0.0",port=10000,debug=True)
接口—flask-restx
介绍
接口编写需要统一,目前尽量遵循restful接口规范
什么是接口文档
在项目开发中,web项目的前后端分离开发,APP开发,需要由前后端工程师共同定义接口,编写接口文档,之后大家都根据这个接口文档进行开发,到项目结束前都要一直维护
为什么要写接口文档
1、项目开发过程中前后端工程师有一个统一的文件进行沟通交流开发
 2、项目维护中或者项目人员更迭,方便后期人员查看、维护
flask-restx的安装
python 2.7 或则 3.4+
pip install flask-restx
简单的demo
from flask import Flask
# 导入flask_restx的Api、Resource类
from flask_restx import Resource, Api
# 实例化flask
app = Flask(__name__)
# 实例化flask_restx 的Api对象,绑定flask的app
api = Api(app)
# 注意这里使用api.route()
# 而不是app.route()
@api.route('/hello/') # 有时候浏览器中输入url会在url的后面自动加一个 '/'
# 定义一个helloworld,需要基础fask_restx 中的Resource类
class HelloWorld(Resource):
    # restful 风格的get方法
    def get(self):
        return {'hello': 'world'}
    # resful 风格的post方法
    def post(self):
        return {"post": "success"}
if __name__ == '__main__':
  	# 注意启动时依旧用app.run()
    app.run(debug=True)
添加路由的方式
- 装饰器
- api的add_resource()方法
from flask import Flask
from flask_restx import Api, Resource
# 实例化Flask()
app = Flask(__name__)
# flask_restx的api绑定到Flask()实例
api = Api(app)
# flask_restx 的api通过装饰器添加路由
@api.route('/login')
class Test(Resource):
    def get(self):
        return {"code": 0, "msg": "flask restx login ssuccess"}
# 通过add_resource()新增一个地址
api.add_resource(Test, '/login2')
if __name__ == '__main__':
    app.run(debug=True)
flask restx集成Swagger
swagger 用于编写一个清晰的接口文档,入参、返回值等信息,自动生成接口文档。
namespace的使用
解决路由分类问题。
不实用namespace进行分类时
from flask import Flask
from flask_restx import Resource, Api
app = Flask(__name__)
api = Api(app)
# 接口路径定义到类上,对应的不同请求操作创建不同的方法
@api.route("/case")
class TestCase(Resource):
    # restful 风格的 get 方法
    def get(self):
        return {"code": 0, "msg": "get success"}
    # restful 风格的 post 方法
    def post(self):
        return {"code": 0, "msg": "post success"}
    # restful 风格的 put 方法
    def put(self):
        return {"code": 0, "msg": "put success"}
    # restful 风格的 delete 方法
    def delete(self):
        return {"code": 0, "msg": "delete success"}
@api.route("/demo")
class Demo(Resource):
    # restful 风格的 get 方法
    def get(self):
        return {"code": 0, "msg": "get success"}
    # restful 风格的 post 方法
    def post(self):
        return {"code": 0, "msg": "post success"}
    # restful 风格的 put 方法
    def put(self):
        return {"code": 0, "msg": "put success"}
    # restful 风格的 delete 方法
    def delete(self):
        return {"code": 0, "msg": "delete success"}
if __name__ == '__main__':
    app.run(debug=True)
效果:











