Why do we need alias=_id in pydantic model of fastapi?

From Getting Started with MongoDB and FastAPI | MongoDB, this pydantic model has id field with alias _id.

  1. What is the significance of this alias?
  2. Must allow_population_by_field_name = True be added for this alias to be used to intended effect or having default False works too?
class StudentModel(BaseModel):
    id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
    name: str = Field(...)
    email: EmailStr = Field(...)
    course: str = Field(...)
    gpa: float = Field(..., le=4.0)

    class Config:
        allow_population_by_field_name = True
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}
        schema_extra = {
            "example": {
                "name": "Jane Doe",
                "email": "jdoe@example.com",
                "course": "Experiments, Science, and Fashion in Nanophotonics",
                "gpa": "3.0",
            }
        }

Can someone more clearly explain the datatypes at each stage of the request/response data transformation pipeline? (Pydantic(fastapi) ↔ pymongo driver ↔ mongodb )
I’m not sure which stage expects/produces id and which stage expects/produces _id, and why the api should accept both id and _id.
I’m also confused about 3 cases when is id designed to be

  • automatically generated by mongodb
  • generated by driver and passed into mongodb
  • generated by pydantic and passed to driver to mongodb.

which the article wasn’t clear at explaining during the alias section.

That article says We set this id value automatically to an ObjectId string, so you do not need to supply it when creating a new student.
Does this mean the alias of _id only comes into play when someone calls fastapi endpoint and provided an _id in body of post request, so it doesn’t have to be automatically created by pydantic?

Is case 1 and 2 above even relevant when working with fastapi (when users interact only with the api)?
The article says “when creating a new student”. What happens if I had already inserted the data directly through mongo shell or driver (meaning not going through pydantic), and I only use fastapi to read data, does this mean this whole id aliasing thing can be ignored?
Furthermore, does it also mean I don’t even have to make any pydantic models if i only want to write a read-only fastapi?

Hi @Han_N_A and welcome to the forums!

In MongoDB, a document must have a field name _id. This is reserved for use as a primary key; its value must be unique in the collection, and is immutable. See also MongoDB Field Names. While in Pydantic, the underscore prefix of a field name would be treated as a private attribute. The alias is defined so that the _id field can be referenced.

The StudentModel utilises _id field as the model id called id. This means, whenever you are dealing with the student model id, in the database this will be stored as _id field name instead.

Depends on the application use case. If the application needs to be able to accept id input in the creation, then yes. Otherwise, if the application will just create id value automatically then you can set this to False.

The reason why allow_population_by_field_name is True, is so that the application can accept a student model creation with id field. If you were to set this option to False, a field value of id input will be ignored in the creation of student model. i.e. in def create_student().

Although the API accepts _id because of the alias, you should just use id throughout the application. The clients that consumes the API would likely need to handle _id in the JSON response.

You would need the alias to translate id to _id as a typed return, but you won’t need the allow_population_by_field_name (default False)

You can use FastAPI without Pydantic models and just utilise Body. See FastAPI without Pydantic

Regards,
Wan.

4 Likes

Due to recent updates in MongoDB, is this still a valid method for Pydantic to validate ObjectId in FastAPI:

1 Like