FastAPI x GenAI

Body - Fields

What about the fields inside a Pydantic model? 🤔

Our Blog model has a title and content, but right now any string can sail through. An empty title? Fine. A 5000-character title? Also fine. We want rules on the individual fields, and we want them living right inside the model where they belong. That is exactly the job of Pydantic's Field.

Importing Field

Here is the one thing that trips people up, so let's get it out of the way first.

from pydantic import BaseModel, Field

Let's review:

  1. Field comes from pydantic, not from fastapi. Notice the difference from Query, Path, and Body, which all come from fastapi.

  2. It sits next to BaseModel in the same import line, since both are Pydantic tools.

Mix this up and you will get an import error wondering where Field went. Keep it with Pydantic. 🙂

Adding rules to model fields

Now let's put Field to work on our Blog model.

from typing import Annotated, Optionalfrom fastapi import Body, FastAPIfrom pydantic import BaseModel, Fieldapp = FastAPI()class Blog(BaseModel):    title: str = Field(min_length=3, max_length=100)    content: str = Field(description="The full body of the blog post")    rating: Optional[float] = Field(default=None, gt=0, le=5)    is_active: bool = True@app.put("/blog/{blog_id}")async def update_blog(blog_id: int, blog: Annotated[Blog, Body(embed=True)]):    return {"blog_id": blog_id, "blog": blog}

Let's understand it:

  1. title now must be between 3 and 100 characters. Send a one-letter title and FastAPI rejects it before your code runs.

  2. content carries a description. That does not validate anything, it just enriches the auto-generated docs so the field explains itself.

  3. rating is optional with a default of None, but if it is sent it must be greater than 0 and no more than 5. That is the same gt and le we used with Path numbers earlier.

  4. is_active stays a plain field with a default. Not every field needs a Field. Use it only where you want extra rules or metadata.

If a client sends a rating of 9, FastAPI sends back a clean validation error pointing right at the rating field. No manual checks anywhere in your function.

Field is imported from pydantic, while Query, Path, and Body come from fastapi. They behave almost identically, but they live in different packages. When an import error shows up here, this swap is usually the reason. 😁 Been there, done that :(