fastapi学习()

Get请求


from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_root(item_id: int):
    return {"item_id": item_id}

# 在最下面加上 这一句
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

这种是直接写在请求路径里面的item_id,就是路径参数,(但是个人不喜欢用)
请求示例url, 比如本地8000端口启动 http://127.0.0.1:8000/items/10
启动方式,如文件名为main.py(不限制但是必须和启动的文件名对应) 都是测试环境启动
安装pip install uvicorn才能使用


from fastapi import FastAPI

app = FastAPI()

@app.get("/bar")
async def read_item(name: str, age: int=18): # tip: 和python默认参数一样,有默认参数写在后面
    return {"name": name, "age": age}

这种name和age就是查询参数方式GET请求,也就是最常见的?和&符号请求方式了
如上请求示例url: http://127.0.0.1:8000/bar?age=22&name=foo

from typing import Optional
from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/bar/{foo}")
async def read_item(
        foo: int = Path(1, title='描述'),
        age: int = Query(..., le=120, title="年龄"),
        name: Optional[str] = Query(None, min_length=3, max_length=50, regex="^xiao\d+$")
):
    return {"foo": foo, "age": age, "name": name}

上述GET请求合法的请求url是

http://127.0.0.1:8000/bar/123?age=18 # Query(…)表示没有默认参数必须得传

or或者

http://127.0.0.1:8000/bar/123?age=18&name=xiao1 # name可以不传,传了就要符合正则的限制xiao开头数字结尾
路径参数使用 Path 查询参数使用Query, 可以查看Path和Query的源码,其实现方式和使用参数方式都差不多,我理解的就是用来验证不用的请求方式的参数。参数有很多验证规则
以上验证参数简单描述
le 验证数字age最大不超过120
min_length 验证name最短3个字符
max_length 验证name最长50个字符
regex 这个就是正则验证 必须是xiao开头数字结尾(当然前提你得熟悉正则)
还有就是Query(…, le=120) … 表示没有默认参数,必须要传

POST请求

from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()


@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": exc.errors()})


@app.post("/bar")
async def read_item(
        foo: int = Body(1, title='描述', embed=True),
        age: int = Body(..., le=120, title="年龄", embed=True),
        name: str = Body(..., regex="^xiao\d+$", embed=True)
):
    return {"foo": foo, "age": age, "name": name}

POST请求,与Query或者Path不一样的就是,使用Body函数来限制参数格式, 如下: Body和Query,Path用法基本是一样的。
embed=True 意思是请求体中,使用json key-value形式, 参考官网
正确的请求方式是 注意header请求头里面”accept: application/json”

Python requests发送请求

import requests

res = requests.post("http://127.0.0.1:8000/bar", json={"foo": 1, "age": 12, "name": "xiao123"})
print(res.json())  # {'foo': 1, 'age': 12, 'name': 'xiao123'}

上述demo只能接收application/json json方式的参数,表单POST请求的方式是接收不到参数的,如form-data 只能使用Form接收,下面是示例:
注意必须安装 pip install python-multipart 才能接收Form参数官网传送门


from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}

POST参数验证#
POST方式除了使用Body方法来验证外,更多的时候是使用的pydantic 这个库来验证的
比如以上的POST请求参数就可以换成一下例子

import re
from typing import Optional
from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, validator, conint, constr

app = FastAPI()


class UserInfo(BaseModel):
    foo: int = 1
    age: conint(le=120) = 18
    # 这里 regex验证 我不知道为什么PyCharm提示语法错误
    name: constr(min_length=5, max_length=10, regex=r"^xiao\d+$")  
	
	# 复杂的验证一般用这个
    @validator('name')
    def name_re(cls, v):
        # 自定义验证 正则验证name字段 等同于上面的正则验证
        if not re.match(r"^xiao\d+$", v):
            # 抛出 ValueError pydantic接收到后会向外抛出 ValidationError
            raise ValueError("name格式验证错误")
        return v

# FastAPI RequestValidationError本就是继承的ValidationError, 会捕获到请求参数异常错误
@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": exc.errors()})


@app.post("/bar")
async def read_item(
        user_info: UserInfo
):
    return {"foo": user_info.foo, "age": user_info.age, "name": user_info.name}


if __name__ == "__main__":
    import uvicorn

总结

Path方法获取请求路径里面的参数如 http://127.0.0.1:8000/bar/123
Query方法获取请求路径后面的查询参数如 http://127.0.0.1:8000/bar?name=xiaoming&age=18
Body方法获取请求体里面的参数,前提是请求头得用accept: application/json

————————

Get请求


from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_root(item_id: int):
    return {"item_id": item_id}

# 在最下面加上 这一句
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

这种是直接写在请求路径里面的item_id,就是路径参数,(但是个人不喜欢用)
请求示例url, 比如本地8000端口启动 http://127.0.0.1:8000/items/10
启动方式,如文件名为main.py(不限制但是必须和启动的文件名对应) 都是测试环境启动
安装pip install uvicorn才能使用


from fastapi import FastAPI

app = FastAPI()

@app.get("/bar")
async def read_item(name: str, age: int=18): # tip: 和python默认参数一样,有默认参数写在后面
    return {"name": name, "age": age}

这种name和age就是查询参数方式GET请求,也就是最常见的?和&符号请求方式了
如上请求示例url: http://127.0.0.1:8000/bar?age=22&name=foo

from typing import Optional
from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/bar/{foo}")
async def read_item(
        foo: int = Path(1, title='描述'),
        age: int = Query(..., le=120, title="年龄"),
        name: Optional[str] = Query(None, min_length=3, max_length=50, regex="^xiao\d+$")
):
    return {"foo": foo, "age": age, "name": name}

上述GET请求合法的请求url是

http://127.0.0.1:8000/bar/123?age=18 # Query(…)表示没有默认参数必须得传

or或者

http://127.0.0.1:8000/bar/123?age=18&name=xiao1 # name可以不传,传了就要符合正则的限制xiao开头数字结尾
路径参数使用 Path 查询参数使用Query, 可以查看Path和Query的源码,其实现方式和使用参数方式都差不多,我理解的就是用来验证不用的请求方式的参数。参数有很多验证规则
以上验证参数简单描述
le 验证数字age最大不超过120
min_length 验证name最短3个字符
max_length 验证name最长50个字符
regex 这个就是正则验证 必须是xiao开头数字结尾(当然前提你得熟悉正则)
还有就是Query(…, le=120) … 表示没有默认参数,必须要传

POST请求

from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()


@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": exc.errors()})


@app.post("/bar")
async def read_item(
        foo: int = Body(1, title='描述', embed=True),
        age: int = Body(..., le=120, title="年龄", embed=True),
        name: str = Body(..., regex="^xiao\d+$", embed=True)
):
    return {"foo": foo, "age": age, "name": name}

POST请求,与Query或者Path不一样的就是,使用Body函数来限制参数格式, 如下: Body和Query,Path用法基本是一样的。
embed=True 意思是请求体中,使用json key-value形式, 参考官网
正确的请求方式是 注意header请求头里面”accept: application/json”

Python requests发送请求

import requests

res = requests.post("http://127.0.0.1:8000/bar", json={"foo": 1, "age": 12, "name": "xiao123"})
print(res.json())  # {'foo': 1, 'age': 12, 'name': 'xiao123'}

上述demo只能接收application/json json方式的参数,表单POST请求的方式是接收不到参数的,如form-data 只能使用Form接收,下面是示例:
注意必须安装 pip install python-multipart 才能接收Form参数官网传送门


from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username}

POST参数验证#
POST方式除了使用Body方法来验证外,更多的时候是使用的pydantic 这个库来验证的
比如以上的POST请求参数就可以换成一下例子

import re
from typing import Optional
from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, validator, conint, constr

app = FastAPI()


class UserInfo(BaseModel):
    foo: int = 1
    age: conint(le=120) = 18
    # 这里 regex验证 我不知道为什么PyCharm提示语法错误
    name: constr(min_length=5, max_length=10, regex=r"^xiao\d+$")  
	
	# 复杂的验证一般用这个
    @validator('name')
    def name_re(cls, v):
        # 自定义验证 正则验证name字段 等同于上面的正则验证
        if not re.match(r"^xiao\d+$", v):
            # 抛出 ValueError pydantic接收到后会向外抛出 ValidationError
            raise ValueError("name格式验证错误")
        return v

# FastAPI RequestValidationError本就是继承的ValidationError, 会捕获到请求参数异常错误
@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": exc.errors()})


@app.post("/bar")
async def read_item(
        user_info: UserInfo
):
    return {"foo": user_info.foo, "age": user_info.age, "name": user_info.name}


if __name__ == "__main__":
    import uvicorn

总结

Path方法获取请求路径里面的参数如 http://127.0.0.1:8000/bar/123
Query方法获取请求路径后面的查询参数如 http://127.0.0.1:8000/bar?name=xiaoming&age=18
Body方法获取请求体里面的参数,前提是请求头得用accept: application/json