美文网首页fastapi学习文档fastapi
fastapi教程翻译(九):Body - Nested Mod

fastapi教程翻译(九):Body - Nested Mod

作者: warmsirius | 来源:发表于2019-10-12 23:30 被阅读0次

    使用FastAPI,您可以定义,验证,生成文档和使用任意深度嵌套的模型(这要归功于Pydantic)。

    一、List 字段

    您可以将属性定义为子类型。 例如,Python的list

    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: list = [] 
    

    上面的设定tagslist项目类型,尽管它并没有声明每个项目的类型。

    二、具有子类型的List字段

    但是Python有一种特定的方法来声明带有子类型的列表:

    1. 导入typingList

    首先,导入Python中typing类的List

    from typing import List 
    

    2. 声明List的子类

    声明类型有子类,比如listdicttuple

    • typing 导入
    • 将子类型用花括号包起来: []
    from typing import List
    
    my_list: List[str]
    

    这就是类型声明的所有标准Python语法。

    对具有子类型的模型属性使用相同的标准语法。

    因此,在我们的例子中,我们可以设置tags具体为字符串的列表

    from typing import List
    
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
     tags: List[str] = [] 
    
    @app.put("/items/{item_id}")
    async def update_item(*, item_id: int, item: Item):
        results = {"item_id": item_id, "item": item}
        return results
    

    三、设置类型

    但是当我们思考一下,如果tags里的字符串必须唯一,不能重复。

    并且Python有专门的数据类型对于这种唯一的项目,就是set

    我们可以导入 Set 并且声明 tagsset 的类,子类是 str:

    from typing import Set 
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: Set[str] = set() 
    
    @app.put("/items/{item_id}")
    async def update_item(*, item_id: int, item: Item):
        results = {"item_id": item_id, "item": item}
        return results
    

    这样,即使您收到带有重复数据的请求,该请求也会被转换为一组唯一的项目。

    而且,每当您输出该数据时,即使源重复,它们也将作为一组唯一项输出。

    并且它也会被相应地注释/生成文档。

    四、嵌套的模型

    每个Pydantic模型的每一个属性都有一个类型。

    而且,这个类型可以自身是另一个Pydantic模型。

    因此,您可以使用特定的属性名称,类型和验证来声明深度嵌套的JSON对象。并且,可以任意嵌套。

    1. 定义一个子模型

    例如,我们可以定义Image类型:

    from typing import Set
    
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Image(BaseModel):
        url: str name: str 
    

    2. 使用子模型作为类型

    然后我们可以将其用作属性的类型:

    from typing import Set
    
    from fastapi import FastAPI
    from pydantic import BaseModel
    
    app = FastAPI()
    
    class Image(BaseModel):
        url: str
        name: str
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: Set[str] = []
        image: Image = None 
    
    @app.put("/items/{item_id}")
    async def update_item(*, item_id: int, item: Item):
        results = {"item_id": item_id, "item": item}
        return results
    

    这意味着FastAPI将期望类似于以下内容的请求体:

    {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2,
        "tags": ["rock", "metal", "bar"],
        "image": {
            "url": "http://example.com/baz.jpg",
            "name": "The Foo live"
        }
    }
    

    同样地,在FastAPI声明,您将获得:

    • 编辑器支持(补全),即使是嵌套模型
    • 数据转换
    • 数据验证
    • 自动文档

    五、特殊类型和验证

    除了正常的单数类型,如strintfloat等外,您还可以使用从str继承的更复杂的单数类型。

    要查看所有选项,请查看Pydantic's exotic types。 您将在下一章中看到一些示例。

    例如,在Image模型中,我们需要一个url字段,我们可以将它声明为Pydantic中的UrlStr,而不是简单的str

    from typing import Set
    
    from fastapi import FastAPI
    from pydantic import BaseModel, UrlStr 
    app = FastAPI()
    
    class Image(BaseModel):
        url: UrlStr
        name: str
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: Set[str] = []
        image: Image = None
    
    @app.put("/items/{item_id}")
    async def update_item(*, item_id: int, item: Item):
        results = {"item_id": item_id, "item": item}
        return results
    

    该字符串将被检查为有效的URL,并在 JSON Schema / OpenAPI中进行记录。

    六、带有子模型列表的属性

    您还可以将Pydantic模型用作listset等的子类型:

    from typing import List, Set
    
    from fastapi import FastAPI
    from pydantic import BaseModel, UrlStr
    
    app = FastAPI()
    
    class Image(BaseModel):
        url: UrlStr
        name: str
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: Set[str] = []
        images: List[Image] = None 
    
    @app.put("/items/{item_id}")
    async def update_item(*, item_id: int, item: Item):
        results = {"item_id": item_id, "item": item}
        return results
    

    这将期望(转换,验证,记录等)JSON请求体,例如:

    {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2,
        "tags": [
            "rock",
            "metal",
            "bar"
        ],
        "images": [
            {
                "url": "http://example.com/baz.jpg",
                "name": "The Foo live"
            },
            {
                "url": "http://example.com/dave.jpg",
                "name": "The Baz"
            }
        ]
    }
    

    七、深层嵌套模型

    您可以定义任意深度嵌套的模型:

    from typing import List, Set
    
    from fastapi import FastAPI
    from pydantic import BaseModel, UrlStr
    
    app = FastAPI()
    
    class Image(BaseModel):
        url: UrlStr
        name: str
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
        tags: Set[str] = []
        images: List[Image] = None 
    
    class Offer(BaseModel):
        name: str
        description: str = None
        price: float
        items: List[Item] 
    
    @app.post("/offers/")
    async def create_offer(*, offer: Offer):
        return offer
    

    八、全部列表的请求体

    如果期望的JSON主体的顶级值为JSON数组(Python列表),则可以在函数的参数中声明类型,与Pydantic模型相同:

    images: List[Image]
    

    如下:

    from typing import List
    
    from fastapi import FastAPI
    from pydantic import BaseModel, UrlStr
    
    app = FastAPI()
    
    class Image(BaseModel):
        url: UrlStr
        name: str
    
    @app.post("/images/multiple/")
    async def create_multiple_images(*, images: List[Image]):
        return images
    

    九、编辑器支持

    无论在哪里你都可以得到编辑器支持。

    即使在列表里的项:

    如果您直接使用dict而不是Pydantic模型,那么您将无法获得这种编辑器支持。

    但是您也不必担心它们,传入的dict会自动转换,您的输出也会自动转换为JSON

    十、任意 dict的主体

    您还可以使用某些类型的键和其他类型的值将主体声明为dict

    无需事先知道有效的字段/属性名称是什么(就像Pydantic模型一样)。

    如果你不知道你将要接受到什么样的key,用dict很有用。

    其他有用的情况是当您想使用其他类型的键时,例如 int

    下面来看看这个例子:

    在这种情况下,您可以接受任何dict,只要它具有带有float值的int键即可:

    from typing import Dict
    
    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.post("/index-weights/")
    async def create_index_weights(weights: Dict[int, float]):
        return weights
    

    记住:JSON只支持str作为键。但是Pydantic会自动转换数据

    这意味着,即使您的API客户端只能将字符串作为键发送,只要这些字符串包含纯整数,Pydantic就会对其进行转换并验证它们。

    相关文章

      网友评论

        本文标题:fastapi教程翻译(九):Body - Nested Mod

        本文链接:https://www.haomeiwen.com/subject/hcnxmctx.html