介绍
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用基于类型提示的 Python 3.6 及更高版本。
依赖库的安装
pip install fastapi
pip install uvicorn
第一个程序
源码
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
运行服务:
uvicorn main:app –reload
然后浏览器地扯栏输入: http://127.0.0.1:8000
即可看到效果。
扩展功能
静态文件配置
存放css,js,image ,在当前目录中创建static
文件夹。
安装依赖库
pip install aiofiles
配置静态文件存放路径
from fastapi import FastAPI
from starlette.staticfiles import StaticFiles
app = FastAPI()
# 静态文件配置 mount挂载 第一个参数为应用的前缀,第二个为路径,第三个为别名
app.mount('/static', StaticFiles(directory='static'), name='static')
注意: /static
这个一定要加上 ‘/’ 如果不加的话,会提示下面的错误:
assert path == "" or path.startswith("/"), "Routed paths must start with '/'"
AssertionError: Routed paths must start with '/'
模板中引入静态文件
比如我当前的static
文件夹中有一个demo.css
文件。
<link rel="stylesheet" href="{{ url_for('static',path='demo.css') }}">
模板渲染
- fastapi本身是没有模版渲染功能的,需要你借助于第三方的模版工具
- 该框架默认情况下也是借助于jinja2来做模版渲染(flask也是使用jinja2, 如果用过flask, 默认是装过jinja2)。
安装jinja2
pip install jinja2
创建模板存放路径
在当前目录下创建一个templates
文件夹,用来保存模板文件html。
结构如下:
project
templates
index.html
main.py
main.py
from fastapi import FastAPI
from starlette.templating import Jinja2Templates
from starlette.requests import Request
app = FastAPI()
# 设置模板存放路径
template = Jinja2Templates(directory='templates')
@app.get('/')
async def index(request: Request): # async加了就支持异步 把Request赋值给request
return template.TemplateResponse('index.html',{'request': request})
if __name__ == '__main__':
import uvicorn
uvicorn.run(app=app, host='127.0.0.1', port=8000)
注意:template.TemplateResponse('index.html',{'request': request})
一定要返回reqeust
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<b>asdfasdf</b>
</body>
</html>
表单数据交互
注意: 如果要使用request.form()支持表单“解析”,则为必需 python-multipart 。
pip install python-multipart
如果python-multipart
库没有安装的话,可能会提示:{"detail":"There was an error parsing the body"}
这种错误。
目录结构如下
project
templates
form.html # 表单模板文件
show.html # 显示表单提交过来的数据
main.py
main.py
from fastapi import FastAPI, Form
from starlette.templating import Jinja2Templates
from starlette.requests import Request
app = FastAPI()
# 设置模板存放路径
template = Jinja2Templates(directory='templates')
@app.get('/form') # 接受get请求
async def get_user(request: Request):
return template.TemplateResponse('form.html', {'request': request})
@app.post('/user/') # 接受post请求
async def get_user(request: Request,
username: str = Form('username'), # 直接去请求体里面获取username键对应的值并自动转化成字符串类型
password: str = Form('password')
):
print(username, type(username))
print(password, type(password))
return template.TemplateResponse('show.html', {
'request': request,
'username': username, # 传参给模板
'pwd': password # 传参给模板
})
if __name__ == '__main__':
import uvicorn
uvicorn.run(app=app, host='127.0.0.1', port=8000)
form.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<form action="/user/" method="post">
<div class="form-group">
<label for="exampleInputEmail1">账号</label>
<input type="text" name="username" class="form-control" id="exampleInputEmail1" placeholder="账号">
</div>
<div class="form-group">
<label for="exampleInputPassword1">密码</label>
<input type="password" name="password" class="form-control" id="exampleInputPassword1" placeholder="密码">
</div>
<button type="submit" class="btn btn-success">提交</button>
</form>
</div>
</div>
</body>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</html>
show.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示出表单提交过来的数据</title>
</head>
<body>
<p>账号是:{{ username }}</p>
<p>密码是:{{ pwd }}</p>
</body>
</html>
浏览器访问 http://127.0.0.1:8000/form
文件上传
单文件上传
目录结构如下:
project
static
templates
file_upload.html
file.html
main.py
main.py
from fastapi import FastAPI, Form, File, UploadFile
from starlette.templating import Jinja2Templates
from starlette.requests import Request
import uuid
app = FastAPI()
# 设置模板存放路径
template = Jinja2Templates(directory='templates')
@app.get('/file_upload')
async def index(request: Request): # async加了就支持异步 把Request赋值给request
return template.TemplateResponse('file_upload.html', {'request': request})
@app.post('/file/') # 接受post请求
async def get_user(request: Request,
file: bytes = File('file'), # # 把文件对象转为bytes类型
file_obj: UploadFile = File('file_obj'), # UploadFile转为文件对象
info: str = Form('info') # 获取普通键值对
):
# 保存上传的文件到static中
path = 'static/' + str(uuid.uuid4()) + '.jpg'
contents = await file_obj.read()
with open(path, "wb") as f:
f.write(contents)
return template.TemplateResponse('file.html', {
'request': request,
'file_size': len(file),
'file_name': file_obj.filename,
'info': info,
'file_content_type': file_obj.content_type
})
if __name__ == '__main__':
import uvicorn
uvicorn.run(app=app, host='127.0.0.1', port=8000)
file_upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单文件上传</title>
</head>
<body>
<form action="/file/" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="file" name="file_obj">
<input type="text" name="info">
<input type="submit" value="上传">
</form>
</body>
</html>
file.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>单个文件</h2>
<h1>{{ file_size }}</h1>
<h1>{{ file_name }}</h1>
<h1>{{ info }}</h1>
<h1>{{ file_content_type }}</h1>
</body>
</html>
运行服务后浏览器访问:http://127.0.0.1:8000/file_upload
。
多文件上传
目录结构如下:
project
static
templates
file_upload.html
file.html
main.py
main.py
from fastapi import FastAPI, Form, File, UploadFile
from starlette.templating import Jinja2Templates
from starlette.requests import Request
from typing import List
app = FastAPI()
# 设置模板存放路径
template = Jinja2Templates(directory='templates')
@app.get('/file_upload')
async def index(request: Request): # async加了就支持异步 把Request赋值给request
return template.TemplateResponse('file_upload.html', {'request': request})
@app.post('/file/') # 接受post请求
async def get_user(request: Request,
file_list: List[UploadFile]=File('file_list'), # UploadFile转为文件对象
):
# 保存上传的多个文件
for file in file_list:
contents = await file.read()
filename = file.filename # 这里使用的是保存件名,如果需要随机文件名的话,请自定义
with open("static/" + filename, "wb") as f:
f.write(contents)
return template.TemplateResponse('file.html', {
'request': request,
'file_names': [file_obj.filename for file_obj in file_list],
})
if __name__ == '__main__':
import uvicorn
uvicorn.run(app=app, host='127.0.0.1', port=8000)
file_upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多文件上传</title>
</head>
<body>
<form action="/file/" method="post" enctype="multipart/form-data">
<input type="file" name="file_list" multiple>
<input type="submit" value="上传">
</form>
</body>
</html>
file.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>多个文件名</h2>
{% for i in file_names %}
<h2>{{ i }}</h2>
{% endfor %}
</body>
</html>