#python #rest #swagger #fastapi #variant
Вопрос:
Скажи, что у меня есть:
from pydantic import BaseModel
from typing import Optional, List
class Create(BaseModel):
code: List[str] = []
args: List[str] = []
Завернутый во что-то вроде
@router.post('/new', status_code=201)
async def create_project(data: Create):
pass
Итак, это code
и/или args
является массивом или единственным значением для запрашивающего?
Таким образом, запрос на одиночный маршрут может содержать что-либо из этого:
{code: "code", args: "arg"}
{code: ["code"], args: "arg"}
{code: ["code"], args: ["arg"]}
{code: "code", args: ["arg"]}
И всегда вызывайте обработчик с реальным типом, который использует списки?
Ответ №1:
Модели Pydantic принимают Union
для определения поля, например:
from typing import List, Union
class Create(BaseModel):
code: Union[str, List[str]] = []
args: Union[str, List[str]] = []
В этом случае оба code
и args
будут принимать либо a str
, либо список/массив str
s.
Оба code
и args
по умолчанию будут пустыми list
.
Остальная часть кода остается прежней, например:
from fastapi import FastAPI, status
app = FastAPI()
@app.post("/create", status_code=status.HTTP_201_CREATED)
async def create_project(data: Create):
return data
Вызов конечной точки с помощью одного элемента:
$ curl -i -X 'POST' 'http://127.0.0.1:8000/create'
-H 'accept: application/json'
-H 'Content-Type: application/json'
-d '{"code": "code", "args": "arg"}'
HTTP/1.1 201 Created
date: Sun, 29 Aug 2021 10:25:57 GMT
server: uvicorn
content-length: 28
content-type: application/json
{"code":"code","args":"arg"}
Вызов конечной точки с несколькими элементами:
$ curl -i -X 'POST' 'http://127.0.0.1:8000/create'
-H 'accept: application/json'
-H 'Content-Type: application/json'
-d '{"code": ["code"], "args": ["arg"]}'
HTTP/1.1 201 Created
date: Sun, 29 Aug 2021 10:27:03 GMT
server: uvicorn
content-length: 32
content-type: application/json
{"code":["code"],"args":["arg"]}
Ответ №2:
У вас есть много возможностей, одна из универсальных-использовать валидатор (или корневой валидатор) и в нем анализировать отдельные значения в список. Вот так:
class Create(BaseModel):
code: List[str] = []
@validator('code', pre=True)
def code_validate(cls, values):
if not isinstance(values, list):
values = [values]
return values
Комментарии:
1. К сожалению, я получаю 422 необработанных объекта из fastapi даже после применения этого с allow_reuse=True
2. В этом случае необходим минимальный воспроизводимый пример