环境: Python3.7.7,Windows10
pip install fastapi uvicorn # fastapi以及启动用
pip install aiofiles jinja2 # 配置使用静态文件和模板文件需要
pip install python-multipart # form表单数据需要
from fastapi import FastAPI
app = FastAPI()
@app.get("/") # 监听GET请求
async def read_root():
return {"Hello": "World"} # 返回json
然后运行即可,默认端口是8000,reload即Debug模式开
端口运行
uvicorn main:app --reload
也可以在main.py里加上这段代码,然后python main.py运行
import uvicorn
if __name__ == '__main__':
uvicorn.run('main:app', reload=True,
host='0.0.0.0', port=8000)
@app.get("/user/{user_id}")
async def user_mod(user_id: int, mod: str = None): # str = None 代表mod参数可以为空
return {
"user_id": user_id,
"mod": mod
}
from fastapi import FastAPI
from fastapi import Form
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel): # 定义一个类用作参数
name: str
price: float
is_offer: bool = None # 该字段可为空
@api.post("/{item_id}")
async def get_item(item_id: int = 1, item: Item, form_param: str = Form(...)): # item需要与Item对象定义保持一致
# Form(...)代表必填
return {
"item_name": item.name,
"item_id": item_id,
'form_param': form_param # 这是form参数
}
from enum import Enum
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName): # 限定参数必须是ModelName枚举中的
pass
return model_name
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {
"file_path": file_path
}
具体可以看:请求文件
这里简单使用下
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(
file: bytes = File(...)
):
return {"file_size": len(file)}
# coding=utf-8
# !/usr/bin/python -u
import codecs
import time
import sys
from fastapi import FastAPI, Depends, Header, HTTPException, Request
import uvicorn
from fastapi.middleware.cors import CORSMiddleware
from starlette.templating import Jinja2Templates
from starlette.staticfiles import StaticFiles
from common.Config import app_config
from appapi import api
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
app = FastAPI(title='workapp',
description='图片转文字工具',
version='1.0.0')
async def get_token_header(x_token: str = Header(...)): # 这里可以做鉴权使用
if x_token != "fake-super-secret-token":
raise HTTPException(status_code=400, detail="X-Token header invalid")
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# 中间件
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
# 挂载静态文件,指定目录
app.mount("/static", StaticFiles(directory="static"),
name="static")
# 模板目录
templates = Jinja2Templates(directory="templates")
# app.include_router(home, prefix='/home', tags=['home'],
# responses={404: {'description': 'NOT FOUND'}})
# 配置router
app.include_router(api, prefix='/api',
responses={404: {'description': 'NOT FOUND'}})
# cors
app.add_middleware(CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"], )
if __name__ == '__main__':
# app_config是创建在Config文件里
uvicorn.run('main:app', reload=app_config.DEBUG,
host='0.0.0.0', port=app_config.PORT)
from fastapi import APIRouter
api = APIRouter()
from . import Index, User, Convert, UserMembership, UserConversion
class Config(object):
# 通用配置
...
class DevConfig(Config):
ENV_NAME = "DEV"
# 开发环境配置
DEBUG = True
PORT = 8000
# 关系型数据库的配置
MYSQL_HOST = "127.0.0.1"
MYSQL_USER = "..."
MYSQL_PASSWORD = "..."
MYSQL_PORT = 3369
# 非关系型数据库的配置
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
REDIS_PASSWORD = "..."
class ReleaseConfig(Config):
ENV_NAME = "Release"
# 发布环境
...
# TODO 更改配置需要修改这里 LocalConfig ReleaseConfig
app_config = DevConfig
appapi目录下User.py
from . import api
import time
import random
from fastapi import Query, Form, Depends
from starlette.requests import Request
from pydantic import BaseModel
from model.WAModel import WaUser, WaUserMembership
from model.ParamModel import User
from common import Func, Utils, Redis
async def verifyToken(user_token: str=Form(...)):
""" 验证token并返回 """
redis = Redis.getRedis()
cache_key = "user_auth_token_" + user_token
user_dict = redis.hgetall(cache_key)
new_data = {key.decode('utf-8'): value.decode('utf-8') for (key, value) in user_dict.items()}
if new_data == {}:
raise HTTPException(status_code=401, detail='verify token failed',
headers={'X-Error': "There goes my error"})
else:
return new_data
# summary是简介直接显示在目录上,description是详细介绍
@api.post('/user/register', tags=['用户'], description='用户注册或重设密码', summary='注册或修改密码')
async def userRegister(u_phone: str = Form(...), u_password: str = Form(...),
verify_code: str = Form(...)):
user = WaUser.get_or_none(u_phone=u_phone)
# redis对象
redis = Redis.getRedis()
# 手机验证码
cache_key = '%s_verify_code' % u_phone
redis_verify_code = redis.get(cache_key)
if not redis_verify_code:
return Func.jsonResult({'verify_code': verify_code}, '验证码已过期,请重新请求', 200000500)
if redis.get(cache_key).decode('utf-8') != verify_code:
return Func.jsonResult({'verify_code': verify_code}, '验证码不正确', 200000500)
salt = Func.md5(Func.randomStr(20))
# MD5加盐加密
enctyped_password = Func.md5(u_password + salt)
if user:
# 修改密码
user.u_password = enctyped_password
user.u_password_salt = salt
user.save()
else:
# 新用户创建
user = WaUser.create(u_phone=u_phone, u_password=enctyped_password,
u_password_salt=salt)
# 这个是自定义的返回格式
return Func.jsonResult({'u_id': user.u_id})
@api.post('/sign_in', tags=['用户'], summary='登录获取token', description='登录获取token')
async def signIn(*, request: Request, u_phone: str = Form(...), u_password: str = Form(...)):
try:
wa_user = WaUser.get(WaUser.u_phone == u_phone)
if wa_user.u_password != Func.md5(u_password + wa_user.u_password_salt):
# jsonResult这个函数是公司通用定义的response格式,这里写成自己的即可
return Func.jsonResult({}, '密码错误', 200000500)
token_expire_at = int(time.time()) + 86400 * 30
token = "USER:" + Func.md5((wa_user.u_phone + wa_user.u_password + str(token_expire_at)))
dt = {
"user_id": wa_user.u_id,
"user_nickname": wa_user.u_phone,
"user_token": token,
"user_token_expired_at": token_expire_at,
}
# 修改
wa_user.u_token = token
wa_user.u_token_expire_time = token_expire_at
wa_user.u_login_time = int(time.time())
client_ip = request.client.host
wa_user.u_login_ip = Utils.ip2long(client_ip)
wa_user.save()
# token存入redis
rds = Redis.getRedis()
cache_key = "user_auth_token_" + token
rds.hmset(cache_key, dt)
rds.expire(cache_key, 30 * 86400)
return Func.jsonResult({"user": dt})
except Exception as e:
print(e)
return Func.jsonResult({}, '用户不存在', 200000500)
@api.post('/user/info', tags=['用户'], description='用户信息', summary='用户信息')
async def userInfo(*, sign_in_user: dict = Depends(verifyToken)):
""" 用token用户信息 """
user_id = sign_in_user.get('user_id')
_where = (WaUser.u_id == user_id)
user_info = WaUser.select(WaUser.u_id,
WaUser.u_avatar, WaUser.u_phone,
WaUser.u_reg_time,
WaUserMembership.um_grade,
WaUserMembership.um_total_num,
WaUserMembership.um_rest_num,
WaUserMembership.um_expire_time).join(WaUserMembership,
on=(WaUser.u_id == WaUserMembership.um_u_id)).where(_where).dicts()
user_info = user_info[0]
return Func.jsonResult(user_info)