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)
效果: