接收请求参数类型的简单了解

一个 url 的组成 protocol :// hostname[:port] / path / [;parameters][?query]#fragment

查询参数 Query

@app.get("/query/")
async def query(item: str,  age: int, sex: bool = False,):
    return {'sex': sex}

# 传递参数 /query/?item=sa&sex=1&age=18
# 路由中:sex=0 or sex=false or ...
# sex === False or True

参数如果没有默认值则为必须传入的

路径参数 parameters Path

@app.get("/as/{item}/")
async def test(item: str):
  # 函数定义中传入的参数值必须与路由中定义的名字相同,不同则会作为url的查询参数 query
  return {'item': item}

# 除非此路由定义在上面,否则永远不会被访问
@app.get("/as/")
async def test1():
  return {'item': item}

将会匹配路由 /as/+, 但不会匹配/as/+/+++ 参数类型为 str. 实际生成的路由为 /as/(+)/ (后面的斜杠来自路由的定义)

如果有两个路由 gat:/as/{item}/ get:/as/ 此时访问 as 就转到 as/item/ 所有不要再主路由上直接使用路径参数

表单参数接收 Form

from fastapi import FastAPI, Form

app = FastAPI()

@app.post('/user/')
def user(uname: str = Form(...), password: str = Form(...)):
    print('uname', uname)
    print('pw', password)
    # 不再渲染模板
    return {'uname': uname, 'password': password}
<body>
<form action="/user/" method="post">
    <input type="text" name="uname">
    <input type="password" name="password">
    <input type="submit">
</form>
</body>

文件接收

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}

# 多文件上传
@app.post("/uploadfiles/")
async def create_upload_files(files: List[UploadFile] = File(...)):
    return {"filenames": [file.filename for file in files]}

要声明文件主体,您需要使用File,因为否则参数将被解释为查询参数或主体( JSON )参数。

  • 如果将路径操作函数参数的类型声明为bytesFastAPI将为您读取文件,并且您将收到内容bytes。这意味着全部内容将存储在内存中。这对于小文件将非常有效。

使用UploadFile比较bytes有以下优点:

  • 它使用“spooled”文件:
    • 存储在内存中的文件大小上超过限制,文件将存储在磁盘中。
  • 您可以从上传的文件中获取元数据。
  • 它具有类似文件的异步接口。
  • 它公开了一个实际的 PythonSpooledTemporaryFile对象,您可以将其直接传递给需要类似文件的对象的其他库。

uploadfile 的方法:

  • write(data):将datastrbytes)写入文件。
  • read(size):读取sizeint)个文件的字节/字符, 参数为空读取所有。
  • seek(offset):转到文件中的字节位置offsetint
  • close():关闭文件。

Tips: 这些方法都是异步的, 需要使用 await 等待

request bady JSON

请求体是客户端发送到您的 API 的数据。

API 几乎总是必须发送一个响应体,但是客户端并不需要一直发送请求体

定义请求体,需要使用 Pydantic 模型

  • 不能通过GET请求发送请求体

  • 发送请求体数据,必须使用以下几种方法之一:

    • POST (最常见),
    • PUT
    • DELETE
    • PATCH
  • 请求体的类型为 json 格式

可以同时定义Path参数Query参数请求体参数:

from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

app = FastAPI()

@app.put("/items/{item_id}")
async def create_item(
    item_id: int,
    item: Item,
    q: str = None
):
    result = {"item_id": item_id, **item.dict()}
    if q:
        result.update({"q": q})
    return result

参数的验证

查询参数的验证及别名 Query

from fastapi import FastAPI, Query

@app.get("/query/")
async def query(item: str = Query(None, min_length=3, max_length=10), 
                test: int = Query(...)):
    return {'item': item}

# 传入参数item 长度不满足条件则为默认值 None
# test 为必填项

@app.get("/query1/")
async def query1(q: List[str] = Query(['foo', 'bar'],)):
    return {'item': q}

# q 接收一个数组, 这个数组具有两个默认值
# alias="item-q" 指定别名,参数传递必须使用此名

# /query1?item-q=1&item-q=30&q=as 则 q === ['1', '30']

路径参数的验证 Path

@app.get('/path/{aid}/')
async def path(aid: int = Path(..., ge=1, le=10)):
    return {'aid': aid}

# /path/0  err: ensure this value is greater than or equal to 1

请求体参数的验证 Body

您想得到一个带有 key 的 JSON ,并且在 key 对应的包含模型内容,就像声明额外的主体参数时那样,则可以使用嵌入的特殊参数 Body(..., embed=True)

class Item(BaseModel):
    name: str = 'tes'
    description: str = None

class Item1(BaseModel):
    price: float = 1.82
    tax: float = None

@app.post('/body/')
async def query(*, item: Item = Body(..., embed=True)):
    return item

# 则 预期的请求体则会为
# {
#     "item": {
#         "name": "tes",
#         "description": "The pretender",
#     }
# }

而 Body 不传递 embed 参数或者为 Fales 则为:

{
    "name": "Foo",
    "description": "The pretender",
}

而对于多个参数,

class Item2(BaseModel):
    item2: str = None


@app.post('/body/')
async def query(*, item2: Item2, item1: Item1, item: Item = Body({}, embed=False)):
    return [item, item1, item2]

不管 embed 的值如何,传输参数格式必须为:

{
  "item2": {
    "item2": "string"
  },
  "item1": {
    "price": 1.82,
    "tax": 0
  } 
}

Pydantic 模型,属性(字段的验证 Field

from pydantic import BaseModel, Field

class Item3(BaseModel):
    name: str = Field(..., min_length=2)
    sex: bool = Field(False, title="性别", description='true is man')


@app.post('/body/field', description='接口描述及字段约束测试')
def body_field(item: Item3):
    return item

对于一个参数的两个验证产生的冲突,现不完全了解。尽量不要发生这种情况:

def body_field(item: Item3 = Body({})):
    return item

# 此时可以不传入参数,则值为 {}, 代表上面 Item3类定义的约束失效。

更多:

baseModel 定义的数据类型可以嵌套,以便支持复杂的参数

from typing import Set, List
from pydantic import BaseModel, Field, HttpUrl


class Img(BaseModel):
    filename: str = Field(..., regex='^filename\-.*')
    # 默认提供的一些参数验证
    url: HttpUrl
    # 接收任意的字典 {str:float, ...}, 则在验证一些密钥时 很有用
    token: Dict[str, float]


class Item(BaseModel):
    name: List[str] = []
    tags: Set[str] = set()
    imgs: List[Img] = None

传递的参数样式:

{
  "name": [],
  "tags": [],
  "imgs": [
    {
      "filename": "filename-test",
      "url": "http://127.0.0.1:8000/docs",
      "token": {
        "additionalProp1": 0,
      }
    }
  ]
}

还有很多额外的参数类型.... , (官网

这些类属性的元素,也是可以作为其他类型参数的约束的。( query, path

枚举类型路径参数

from fastapi import FastAPI
from enum import Enum

class Name(str, Enum):
    Allan = 'allan'
    Jon = 'jon'
    Bob = 'bob'

@app.get('/name/{who}')
async def get_name(who: Name):
    return {'name': who}

传入的参数必须被枚举类型定义

非常用参数的获取,及验证

@app.get('/cookie/')
def cookie(*, abs_id: str = Cookie(None)):
    return {'abs_id': abs_id}

# 获取cookie中 键为 abs_id 的cookie值
from typing import List
from fastapi import FastAPI, Header

app = FastAPI()


@app.get('/items')
async def items(*, user_agent: str = Header(None),
                users_agent: str = Header(None),    # Null
                x_token: List[str] = Header(None)):
    return {'userAgent': user_agent,
            'x_token': x_token}
  • 对于参数值的匹配是按照参数名来匹配的。

  • x_token 接收的是一个 按照分号分割的字符串如:["a,b,c,d"]. 是因为 hender 它不支持列表. 因为传递形式也是为:"x-token: 'string', 'b,', 'c'". 所以还是字节接收字符串比较好

更多

响应状态码

您可以使用指定响应模型的相同方法,也可以status_code在任何路径操作中使用参数声明用于响应的 HTTP 状态代码. 您可以直接传递int代码,例如404

@app.post("/items/", status_code=201)
async def create_item(name: str):
    return {"name": name}

果您不记得每个数字代码的用途,则可以在中使用快捷方式常量status

from fastapi import FastAPI, status

@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
async def create_item(item: Item):
    return item

该状态代码将在响应中使用,并将添加到 OpenAPI 架构中。

Tips:

您也可以使用from starlette import status

FastAPI提供相同starlette.statusfastapi.status,但它来自 Starlette。

Tips: 你可以标记添加到您的路径操作,传递参数tagsliststr. 它们将被添加到 OpenAPI 架构中,并由自动文档接口使用. @app.get("/users/", tags=["users"])


相关推荐:

来自系列:fastapi

分类 python下文章:

1.0 爬虫的介绍,和requests模块的简单使用

1.1 数据解析的三种方式。正则表达式, bs4, xpath

2.0 多任务(进程,协程,线程)爬虫:验证码识别,返回头储存,ip代理 介绍。 异步是什么,爬虫异步的方式。线程,进程,介绍

2.0.1 协程的 async/await 实现 爬虫 单线程 + 异步协程的实现

3.0 基于selenium 模块的 爬虫操作。 selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。

更多...

评论([[comments.sum]])

发表

加载更多([[item.son.length-2]])...

发表

2020-11 By chuan.

Python-flask & bootstrap-flask

图片外链来自:fghrsh

互联网ICP备案号:蜀ICP备2020031846号