Migrating an application on FastAPI from Pydantic V1 to V2

- Andrés Cruz

En español

In this post I wanted to show some changes that need to be made when upgrading the Pydantic package from version 1 to version 2.

 

A common mistake is about the name of the Config class which is now ConfigDict:

class Task(MyBaseModel):
    ***
    class ConfigDict:
        ***

Is now:

class Task(MyBaseModel):
    ***
    class ConfigDict:
        ***
*  `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0

 

A common mistake is with the orm_mode attribute to convert to dictionaries between Pydantic and database models, for example SQLALchemy:

 

* 'orm_mode' has been renamed to 'from_attributes'
class Task(MyBaseModel):
    class ConfigDict:
        orm_mode = True

Is now:

class Task(MyBaseModel):
    class ConfigDict:
        from_attributes = True

Another mistake is to define the schemas to indicate the sample data:

* 'schema_extra' has been renamed to 'json_schema_extra'
class Task(MyBaseModel):
    ***
    class ConfigDict:
        schema_extra= {
            "example": {
                "id" : 123,
                "name": "Salvar al mundo",
                "description": "Hola Mundo Desc",
                "status": StatusType.PENDING,
                "tag":["tag 1", "tag 2"],
            }
        }

Is now:

class Task(MyBaseModel):
    ***
    class ConfigDict:
        json_schema_extra = {
            "example": {
                "id" : 123,
                "name": "Salvar al mundo",
                "description": "Hola Mundo Desc",
                "status": StatusType.PENDING,
                "tag":["tag 1", "tag 2"],
            }
        }

While working with SQLAlchemy, there was also an update on the function of:

* MovedIn20Warning: The ``declarative_base()`` function is now available as sqlalchemy.orm.declarative_base(). (deprecated since: 2.0) (Background on SQLAlchemy 2.0

Now it imports from:

from sqlalchemy.orm import sessionmaker, declarative_base

The validator decorator has also changed its name:

from pydantic import BaseModel,  ValidationError, validator

class Task(BaseModel):
   id: int
   name: str
   description: str
   status: StatusType
   
   @validator('id')
   def greater_than_zero(cls, v):
       if v <=0 :
           raise ValueError('must be greater than zero')
       return v

Is now:

from pydantic import BaseModel,  ValidationError, field_validator

class Task(BaseModel):
   id: int
   name: str
   description: str
   status: StatusType
   
   @field_validator('id')
   def greater_than_zero(cls, v):
       if v <=0 :
           raise ValueError('must be greater than zero')
       return v
* @validator` validators are deprecated. You should migrate to Pydantic V2 style `@field_validator` validators, see the migration guide for more details. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.0.3/migration/

 

For regular expressions it is no longer regex but pattern:

* DeprecationWarning: `regex` has been depreacated, please use `pattern` instead
    def phone(phone: Annotated[str, Query(regex=r"^(\(?\+[\d]{1,3}\)?)\s?([\d]{1,5})\s?([\d][\s\.-]?){6,7}$", example="+34 111 12-34-56")]):
@app.get("/ep_phone/{phone}") # +34 111 12-34-56
def phone(phone: str = Path(regex=r"^(\(?\+[\d]{1,3}\)?)\s?([\d]{1,5})\s?([\d][\s\.-]?){6,7}$", example="+34 111 12-34-56")):
   return {"phone": phone}

Is now:

@app.get("/ep_phone/{phone}") # +34 111 12-34-56
def phone(phone: str = Path(pattern=r"^(\(?\+[\d]{1,3}\)?)\s?([\d]{1,5})\s?([\d][\s\.-]?){6,7}$", example="+34 111 12-34-56")):
   return {"phone": phone}

Here are some of the changes made to the FastAPI course and book at the project level.

I agree to receive announcements of interest about this Blog.

We'll talk about some changes we need to make when upgrading a project in Pydantic FastAPI 1 to 2.

- Andrés Cruz

En español