FastAPI & Pydantic

Anh-Thi Dinh
draft
⚠️
This is a quick & dirty draft, for me only!

References

Validators

Official doc: Validators - Pydantic

Check ISO-638-1 of an property

1import pycountry
2
3def is_valid_iso_639_1(language_code: str) -> bool:
4    try:
5        language = pycountry.languages.get(alpha_2=language_code)
6        return language is not None
7    except (AttributeError, KeyError):
8        return False
9
10class TranscribeConfigs(BaseModel):
11    inputLanguage: str = Field(default="")
12    outputLanguage: str = Field(default="")
13    specialWords: List[str] = Field(default=[])
14
15    @field_validator('inputLanguage', 'outputLanguage')
16    @classmethod
17    def validate_language_code(cls, v):
18        if v is None or len(v) == 0: # accept optional property
19            return v
20        if not re.match(r'^[a-z]{2}$', v):
21            raise ValueError("Language must be a valid ISO-639-1 two-letter code")
22        return v
Another way using AfterValidator (more)
1def is_valid_iso_639_1(v: str) -> bool:
2    # accept null or empty string (optional prop)
3    if v is None or len(v) == 0:
4        return v
5    try:
6        language = pycountry.languages.get(alpha_2=v)
7        if language is not None:
8            return v
9        raise HTTPException(
10            status_code=422,
11            detail="Language must be a valid ISO-639-1 two-letter code",
12        )
13    except (AttributeError, KeyError):
14        raise HTTPException(
15            status_code=422,
16            detail="Language must be a valid ISO-639-1 two-letter code",
17        )
18
19class TranscribeConfigs(BaseModel):
20    inputLanguage: Annotated[Optional[str], AfterValidator(is_valid_iso_639_1)] = Field(default="", description="ISO 639-1 language code")
21    outputLanguage: Annotated[Optional[str], AfterValidator(is_valid_iso_639_1)] = Field(default="", description="ISO 639-1 language code")
22    specialWords: Optional[List[str]] = Field(default=[], description="List of special words to be transcribed")

/docs

Schema in /docs

Each endpoint in /docs displays a schema that defines its responses and inputs. This section explains how to customize these schemas.
  • Another way for custom response with error code
    • 1class ErrorResponse(BaseModel):
      2    detail: str
      3    
      4@app.post("/upload", response_model=UploadResponse, responses={500: {"model": ErrorResponse}})

Hiển thị form in try out của /docs

Ví dụ để hiển thị được giống vầy khi nhấn “Try it out”
 
1from typing import Annotated
2from fastapi import File, Form, UploadFile
3
4class TranscribeConfigs(BaseModel):
5		file: UploadFile = File(...)
6	  inputLanguage: Optional[str] = None
7	  outputLanguage: Optional[str] = None
8	  specialWords: Optional[List[str]] = None
9
10async def upload( body: Annotated[TranscribeConfigs, Form()]):

Check “Send empty value” by default

1class TranscribeConfigs(BaseModel):
2    inputLanguage: str = Field(default="")