Skip to content

๐ŸŒ– ๐Ÿ“จ ๐Ÿ—„

Warning

๐Ÿ‘‰ ๐Ÿ‘ ๐Ÿง โ”.

๐Ÿšฅ ๐Ÿ‘† โ–ถ๏ธ โฎ๏ธ FastAPI, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿšซ ๐Ÿ’ช ๐Ÿ‘‰.

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“ฃ ๐ŸŒ– ๐Ÿ“จ, โฎ๏ธ ๐ŸŒ– ๐Ÿ‘” ๐Ÿ“Ÿ, ๐Ÿ”‰ ๐Ÿ†Ž, ๐Ÿ“›, โ™’๏ธ.

๐Ÿ‘ˆ ๐ŸŒ– ๐Ÿ“จ ๐Ÿ”œ ๐Ÿ”Œ ๐Ÿ—„ ๐Ÿ”—, ๐Ÿ‘ซ ๐Ÿ”œ ๐Ÿ˜‘ ๐Ÿ› ๏ธ ๐Ÿฉบ.

โœ‹๏ธ ๐Ÿ‘ˆ ๐ŸŒ– ๐Ÿ“จ ๐Ÿ‘† โœ”๏ธ โš’ ๐Ÿ’ญ ๐Ÿ‘† ๐Ÿ“จ Response ๐Ÿ’– JSONResponse ๐Ÿ”—, โฎ๏ธ ๐Ÿ‘† ๐Ÿ‘” ๐Ÿ“Ÿ & ๐ŸŽš.

๐ŸŒ– ๐Ÿ“จ โฎ๏ธ model

๐Ÿ‘† ๐Ÿ’ช ๐Ÿšถโ€โ™€๏ธ ๐Ÿ‘† โžก ๐Ÿ› ๏ธ ๐Ÿ‘จโ€๐ŸŽจ ๐Ÿ”ข responses.

โšซ๏ธ ๐Ÿ“จ dict, ๐Ÿ”‘ ๐Ÿ‘” ๐Ÿ“Ÿ ๐Ÿ”  ๐Ÿ“จ, ๐Ÿ’– 200, & ๐Ÿ’ฒ ๐ŸŽ dictโ“‚ โฎ๏ธ โ„น ๐Ÿ”  ๐Ÿ‘ซ.

๐Ÿ”  ๐Ÿ‘ˆ ๐Ÿ“จ dictโ“‚ ๐Ÿ’ช โœ”๏ธ ๐Ÿ”‘ model, โš— Pydantic ๐Ÿท, ๐Ÿ’– response_model.

FastAPI ๐Ÿ”œ โœŠ ๐Ÿ‘ˆ ๐Ÿท, ๐Ÿ— ๐Ÿšฎ ๐ŸŽป ๐Ÿ”— & ๐Ÿ”Œ โšซ๏ธ โ˜‘ ๐Ÿฅ‰ ๐Ÿ—„.

๐Ÿ–ผ, ๐Ÿ“ฃ โž•1๏ธโƒฃ ๐Ÿ“จ โฎ๏ธ ๐Ÿ‘” ๐Ÿ“Ÿ 404 & Pydantic ๐Ÿท Message, ๐Ÿ‘† ๐Ÿ’ช โœ:

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


class Message(BaseModel):
    message: str


app = FastAPI()


@app.get("/items/{item_id}", response_model=Item, responses={404: {"model": Message}})
async def read_item(item_id: str):
    if item_id == "foo":
        return {"id": "foo", "value": "there goes my hero"}
    return JSONResponse(status_code=404, content={"message": "Item not found"})

Note

โœ”๏ธ ๐Ÿคฏ ๐Ÿ‘ˆ ๐Ÿ‘† โœ”๏ธ ๐Ÿ“จ JSONResponse ๐Ÿ”—.

Info

model ๐Ÿ”‘ ๐Ÿšซ ๐Ÿ• ๐Ÿ—„.

FastAPI ๐Ÿ”œ โœŠ Pydantic ๐Ÿท โšช๏ธโžก๏ธ ๐Ÿ“ค, ๐Ÿ— JSON Schema, & ๐Ÿšฎ โšซ๏ธ โ˜‘ ๐Ÿฅ‰.

โ˜‘ ๐Ÿฅ‰:

  • ๐Ÿ”‘ content, ๐Ÿ‘ˆ โœ”๏ธ ๐Ÿ’ฒ โž•1๏ธโƒฃ ๐ŸŽป ๐ŸŽš (dict) ๐Ÿ‘ˆ ๐Ÿ”Œ:
    • ๐Ÿ”‘ โฎ๏ธ ๐Ÿ“ป ๐Ÿ†Ž, โœ… application/json, ๐Ÿ‘ˆ ๐Ÿ”Œ ๐Ÿ’ฒ โž•1๏ธโƒฃ ๐ŸŽป ๐ŸŽš, ๐Ÿ‘ˆ ๐Ÿ”Œ:
      • ๐Ÿ”‘ schema, ๐Ÿ‘ˆ โœ”๏ธ ๐Ÿ’ฒ ๐ŸŽป ๐Ÿ”— โšช๏ธโžก๏ธ ๐Ÿท, ๐Ÿ“ฅ โ˜‘ ๐Ÿฅ‰.
        • FastAPI ๐Ÿšฎ ๐Ÿ”— ๐Ÿ“ฅ ๐ŸŒ ๐ŸŽป ๐Ÿ”— โž•1๏ธโƒฃ ๐Ÿฅ‰ ๐Ÿ‘† ๐Ÿ—„ โ†ฉ๏ธ โœ… โšซ๏ธ ๐Ÿ”—. ๐Ÿ‘‰ ๐ŸŒŒ, ๐ŸŽ ๐Ÿˆธ & ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ’ช โš™๏ธ ๐Ÿ‘ˆ ๐ŸŽป ๐Ÿ”— ๐Ÿ”—, ๐Ÿšš ๐Ÿ‘ป ๐Ÿ“Ÿ โšก ๐Ÿงฐ, โ™’๏ธ.

๐Ÿ— ๐Ÿ“จ ๐Ÿ—„ ๐Ÿ‘‰ โžก ๐Ÿ› ๏ธ ๐Ÿ”œ:

{
    "responses": {
        "404": {
            "description": "Additional Response",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/Message"
                    }
                }
            }
        },
        "200": {
            "description": "Successful Response",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/Item"
                    }
                }
            }
        },
        "422": {
            "description": "Validation Error",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/HTTPValidationError"
                    }
                }
            }
        }
    }
}

๐Ÿ”— ๐Ÿ”— โž•1๏ธโƒฃ ๐Ÿฅ‰ ๐Ÿ”˜ ๐Ÿ—„ ๐Ÿ”—:

{
    "components": {
        "schemas": {
            "Message": {
                "title": "Message",
                "required": [
                    "message"
                ],
                "type": "object",
                "properties": {
                    "message": {
                        "title": "Message",
                        "type": "string"
                    }
                }
            },
            "Item": {
                "title": "Item",
                "required": [
                    "id",
                    "value"
                ],
                "type": "object",
                "properties": {
                    "id": {
                        "title": "Id",
                        "type": "string"
                    },
                    "value": {
                        "title": "Value",
                        "type": "string"
                    }
                }
            },
            "ValidationError": {
                "title": "ValidationError",
                "required": [
                    "loc",
                    "msg",
                    "type"
                ],
                "type": "object",
                "properties": {
                    "loc": {
                        "title": "Location",
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "msg": {
                        "title": "Message",
                        "type": "string"
                    },
                    "type": {
                        "title": "Error Type",
                        "type": "string"
                    }
                }
            },
            "HTTPValidationError": {
                "title": "HTTPValidationError",
                "type": "object",
                "properties": {
                    "detail": {
                        "title": "Detail",
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ValidationError"
                        }
                    }
                }
            }
        }
    }
}

๐ŸŒ– ๐Ÿ”‰ ๐Ÿ†Ž ๐Ÿ‘‘ ๐Ÿ“จ

๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๐Ÿ‘‰ ๐ŸŽ responses ๐Ÿ”ข ๐Ÿšฎ ๐ŸŽ ๐Ÿ”‰ ๐Ÿ†Ž ๐ŸŽ ๐Ÿ‘‘ ๐Ÿ“จ.

๐Ÿ–ผ, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿšฎ ๐ŸŒ– ๐Ÿ“ป ๐Ÿ†Ž image/png, ๐Ÿ“ฃ ๐Ÿ‘ˆ ๐Ÿ‘† โžก ๐Ÿ› ๏ธ ๐Ÿ’ช ๐Ÿ“จ ๐ŸŽป ๐ŸŽš (โฎ๏ธ ๐Ÿ“ป ๐Ÿ†Ž application/json) โš–๏ธ ๐Ÿ‡ฉ๐Ÿ‡ด ๐Ÿ–ผ:

from typing import Union

from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


app = FastAPI()


@app.get(
    "/items/{item_id}",
    response_model=Item,
    responses={
        200: {
            "content": {"image/png": {}},
            "description": "Return the JSON item or an image.",
        }
    },
)
async def read_item(item_id: str, img: Union[bool, None] = None):
    if img:
        return FileResponse("image.png", media_type="image/png")
    else:
        return {"id": "foo", "value": "there goes my hero"}

Note

๐Ÿ‘€ ๐Ÿ‘ˆ ๐Ÿ‘† โœ”๏ธ ๐Ÿ“จ ๐Ÿ–ผ โš™๏ธ FileResponse ๐Ÿ”—.

Info

๐Ÿšฅ ๐Ÿ‘† โœ” ๐ŸŽ ๐Ÿ“ป ๐Ÿ†Ž ๐ŸŽฏ ๐Ÿ‘† responses ๐Ÿ”ข, FastAPI ๐Ÿ”œ ๐Ÿค” ๐Ÿ“จ โœ”๏ธ ๐ŸŽ ๐Ÿ“ป ๐Ÿ†Ž ๐Ÿ‘‘ ๐Ÿ“จ ๐ŸŽ“ (๐Ÿ”ข application/json).

โœ‹๏ธ ๐Ÿšฅ ๐Ÿ‘† โœ”๏ธ โœ” ๐Ÿ›ƒ ๐Ÿ“จ ๐ŸŽ“ โฎ๏ธ None ๐Ÿšฎ ๐Ÿ“ป ๐Ÿ†Ž, FastAPI ๐Ÿ”œ โš™๏ธ application/json ๐Ÿ™† ๐ŸŒ– ๐Ÿ“จ ๐Ÿ‘ˆ โœ”๏ธ ๐Ÿ‘จโ€๐Ÿ’ผ ๐Ÿท.

๐ŸŒ€ โ„น

๐Ÿ‘† ๐Ÿ’ช ๐ŸŒ€ ๐Ÿ“จ โ„น โšช๏ธโžก๏ธ ๐Ÿ’— ๐Ÿฅ‰, ๐Ÿ”Œ response_model, status_code, & responses ๐Ÿ”ข.

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“ฃ response_model, โš™๏ธ ๐Ÿ”ข ๐Ÿ‘” ๐Ÿ“Ÿ 200 (โš–๏ธ ๐Ÿ›ƒ 1๏ธโƒฃ ๐Ÿšฅ ๐Ÿ‘† ๐Ÿ’ช), & โคด๏ธ ๐Ÿ“ฃ ๐ŸŒ– โ„น ๐Ÿ‘ˆ ๐ŸŽ ๐Ÿ“จ responses, ๐Ÿ”— ๐Ÿ—„ ๐Ÿ”—.

FastAPI ๐Ÿ”œ ๐Ÿšง ๐ŸŒ– โ„น โšช๏ธโžก๏ธ responses, & ๐ŸŒ€ โšซ๏ธ โฎ๏ธ ๐ŸŽป ๐Ÿ”— โšช๏ธโžก๏ธ ๐Ÿ‘† ๐Ÿท.

๐Ÿ–ผ, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“ฃ ๐Ÿ“จ โฎ๏ธ ๐Ÿ‘” ๐Ÿ“Ÿ 404 ๐Ÿ‘ˆ โš™๏ธ Pydantic ๐Ÿท & โœ”๏ธ ๐Ÿ›ƒ description.

& ๐Ÿ“จ โฎ๏ธ ๐Ÿ‘” ๐Ÿ“Ÿ 200 ๐Ÿ‘ˆ โš™๏ธ ๐Ÿ‘† response_model, โœ‹๏ธ ๐Ÿ”Œ ๐Ÿ›ƒ example:

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


class Message(BaseModel):
    message: str


app = FastAPI()


@app.get(
    "/items/{item_id}",
    response_model=Item,
    responses={
        404: {"model": Message, "description": "The item was not found"},
        200: {
            "description": "Item requested by ID",
            "content": {
                "application/json": {
                    "example": {"id": "bar", "value": "The bar tenders"}
                }
            },
        },
    },
)
async def read_item(item_id: str):
    if item_id == "foo":
        return {"id": "foo", "value": "there goes my hero"}
    else:
        return JSONResponse(status_code=404, content={"message": "Item not found"})

โšซ๏ธ ๐Ÿ”œ ๐ŸŒ ๐ŸŒ€ & ๐Ÿ”Œ ๐Ÿ‘† ๐Ÿ—„, & ๐ŸŽฆ ๐Ÿ› ๏ธ ๐Ÿฉบ:

๐ŸŒ€ ๐Ÿ”ข ๐Ÿ“จ & ๐Ÿ›ƒ ๐Ÿ•

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ’š โœ”๏ธ ๐Ÿ” ๐Ÿ“จ ๐Ÿ‘ˆ โœ” ๐Ÿ“š โžก ๐Ÿ› ๏ธ, โœ‹๏ธ ๐Ÿ‘† ๐Ÿ’š ๐ŸŒ€ ๐Ÿ‘ซ โฎ๏ธ ๐Ÿ›ƒ ๐Ÿ“จ ๐Ÿ’š ๐Ÿ”  โžก ๐Ÿ› ๏ธ.

๐Ÿ“š ๐Ÿ’ผ, ๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๐Ÿ โš’ "๐Ÿ—" dict โฎ๏ธ **dict_to_unpack:

old_dict = {
    "old key": "old value",
    "second old key": "second old value",
}
new_dict = {**old_dict, "new key": "new value"}

๐Ÿ“ฅ, new_dict ๐Ÿ”œ ๐Ÿ”Œ ๐ŸŒ ๐Ÿ”‘-๐Ÿ’ฒ ๐Ÿ‘ซ โšช๏ธโžก๏ธ old_dict โž• ๐Ÿ†• ๐Ÿ”‘-๐Ÿ’ฒ ๐Ÿ‘ซ:

{
    "old key": "old value",
    "second old key": "second old value",
    "new key": "new value",
}

๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๐Ÿ‘ˆ โš’ ๐Ÿค-โš™๏ธ ๐Ÿ”ข ๐Ÿ“จ ๐Ÿ‘† โžก ๐Ÿ› ๏ธ & ๐ŸŒ€ ๐Ÿ‘ซ โฎ๏ธ ๐ŸŒ– ๐Ÿ›ƒ ๐Ÿ•.

๐Ÿ–ผ:

from typing import Union

from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


responses = {
    404: {"description": "Item not found"},
    302: {"description": "The item was moved"},
    403: {"description": "Not enough privileges"},
}


app = FastAPI()


@app.get(
    "/items/{item_id}",
    response_model=Item,
    responses={**responses, 200: {"content": {"image/png": {}}}},
)
async def read_item(item_id: str, img: Union[bool, None] = None):
    if img:
        return FileResponse("image.png", media_type="image/png")
    else:
        return {"id": "foo", "value": "there goes my hero"}

๐ŸŒ– โ„น ๐Ÿ”ƒ ๐Ÿ—„ ๐Ÿ“จ

๐Ÿ‘€ โšซ๏ธโ” โšซ๏ธโ” ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ”Œ ๐Ÿ“จ, ๐Ÿ‘† ๐Ÿ’ช โœ… ๐Ÿ‘‰ ๐Ÿ“„ ๐Ÿ—„ ๐Ÿ”ง:

  • ๐Ÿ—„ ๐Ÿ“จ ๐ŸŽš, โšซ๏ธ ๐Ÿ”Œ Response Object.
  • ๐Ÿ—„ ๐Ÿ“จ ๐ŸŽš, ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ”Œ ๐Ÿ•ณ โšช๏ธโžก๏ธ ๐Ÿ‘‰ ๐Ÿ”— ๐Ÿ”  ๐Ÿ“จ ๐Ÿ”˜ ๐Ÿ‘† responses ๐Ÿ”ข. โœ… description, headers, content (๐Ÿ”˜ ๐Ÿ‘‰ ๐Ÿ‘ˆ ๐Ÿ‘† ๐Ÿ“ฃ ๐ŸŽ ๐Ÿ”‰ ๐Ÿ†Ž & ๐ŸŽป ๐Ÿ”—), & links.