Pydantic for FastAPI

FastAPI is a modern async framework for Python. According to Python developers survey 2020, FastAPI is the 3rd most popular web framework for python.

What makes FastAPI so popular?

Async
Fast
Easy to Code and fast learning curve.
Data vali…


This content originally appeared on DEV Community and was authored by Amal Shaji

FastAPI is a modern async framework for Python. According to Python developers survey 2020, FastAPI is the 3rd most popular web framework for python.

What makes FastAPI so popular?

  • Async
  • Fast
  • Easy to Code and fast learning curve.
  • Data validation via Pydantic
  • Automatic docs

Take a look at all the FastAPI features.

Pydantic is a python library for data parsing and validation using Python type hints. It is the fastest python data validation library.

Pydantic for FastAPI

1. BaseSettings for reading environment variables

This requires python-dotenv installed.

pip install python-dotenv

Dummy .env file:

DB_NAME=postgres
DB_PASS=postgres
DB_URL=postgresql://postgres:postgres@127.0.0.1:5432/postgres

DEBUG=True
SEED=42
# env.py

from pydantic import BaseSettings, PostgresDsn


class Settings(BaseSettings):
    db_name: str
    db_pass: str
    db_url: PostgresDsn
    debug: bool
    seed: int

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"


settings = Settings()
print(settings)

Output:

db_name='postgres' db_pass='postgres' db_url=PostgresDsn('postgresql://postgres:postgres@127.0.0.1:5432/postgres', scheme='postgresql', user='postgres', password='postgres', host='127.0.0.1', host_type='ipv4', port='5432', path='/postgres') debug=True seed=42
  • The environment variables are automatically loaded by name.
  • They are converted to the types specified by type hints.

By default, all variables are case-insensitive.

You can also use an alias for loading env values. For example, your env variable is DATABASE_URL, but you need to load it as db_url.

from pydantic import BaseSettings, Field, PostgresDsn

class Settings(BaseSettings):
    db_url: PostgresDsn = Field(..., env="DATABASE_URL")

Reading the env file is only required if the values are not in the system environment. This process is costly, especially when read for each request. So cache the values using lru_cache.

from functools import lru_cache
# other imports


class Settings(BaseSettings):
    # All fields, yadayadayada

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"


@lru_cache
def get_settings() -> Settings:
    return Settings()


settings = get_settings()

Every time the get_settings is called, the cached values are returned.

2. Validators for custom data validation

Validators are applied to BaseModel to perform custom validation.

Basic BaseModel + FastAPI usage:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class User(BaseModel):
    email: str  # use EmailStr from pydantic
    username: str
    password: str


@app.post("/")
async def register(user: User):
    return user

Test it out using httpie:

➜ http POST 127.0.0.1:8000 email=test@test.com username=amal password=amal
HTTP/1.1 200 OK
content-length: 61
content-type: application/json
date: Wed, 19 May 2021 12:20:06 GMT
server: uvicorn

{
    "email": "test@test.com",
    "password": "amal",
    "username": "amal"
}

Let's use @validator from pydantic to perform some operation on the BaseModel before the view, register, receives it.

from pydantic import BaseModel, validator

class User(BaseModel):
    email: str  # use EmailStr from pydantic
    username: str
    password: str

    @validator("password")
    def hash_the_password(cls, password: str):
        return f"Fast-Insecure-Hash-{password}"
➜ http POST 127.0.0.1:8000 email=test@test.com username=amal password=amal
HTTP/1.1 200 OK
content-length: 80
content-type: application/json
date: Wed, 19 May 2021 12:39:06 GMT
server: uvicorn

{
    "email": "test@test.com",
    "password": "Fast-Insecure-Hash-amal",
    "username": "amal"
}

You can also validate a particular field with the rest of the fields.

@validator("password")
def hash_the_password(cls, password, values, **kwargs):
    print(values.keys())
    return password

This prints dict_keys(['email', 'username']) to stdout. The pydantic fields are validated in sequence, and the values dict carries the already validated fields.

In this case, since we are validating the password field, all the above fields are available to use.

You can use Root Validator to use the entire model's data. By default, the root validator gets data after all the fields are validated(i.e., the default validation).

@root_validator
def test_root_validator(cls, values):
    print(values.keys())
    return values

Output:

dict_keys(['email', 'username', 'password'])

3. schema_extra for providing examples in docs

With the previous example running, if you navigate to http://127.0.0.1:8000/docs, you could see the interactive docs by FastAPI.

Interactive API docs by FastAPI

Instead of string for all values, let's write some custom data for the examples.

class User(BaseModel):
    email: str  # use EmailStr from pydantic
    username: str
    password: str

    class Config:
        schema_extra = {
            "example": {
                "email": "test@test.com",
                "username": "amal",
                "password": "amal",
            }
        }

Interactive API docs with custom data

You can also use fake data libraries like Faker to generate random data.

Setting the example data can also be achieved like so:

class User(BaseModel):
    email: str = Field(..., example="test@test.com")
    username: str = Field(..., example="amal")
    password: str = Field(..., example="amal")

Conclusion

Pydantic is an amazing tool for data validation. FastAPI uses pydantic to help build better APIs. For more amazing features of pydantic, read the official documentation.


This content originally appeared on DEV Community and was authored by Amal Shaji


Print Share Comment Cite Upload Translate Updates
APA

Amal Shaji | Sciencx (2021-05-28T16:45:09+00:00) Pydantic for FastAPI. Retrieved from https://www.scien.cx/2021/05/28/pydantic-for-fastapi/

MLA
" » Pydantic for FastAPI." Amal Shaji | Sciencx - Friday May 28, 2021, https://www.scien.cx/2021/05/28/pydantic-for-fastapi/
HARVARD
Amal Shaji | Sciencx Friday May 28, 2021 » Pydantic for FastAPI., viewed ,<https://www.scien.cx/2021/05/28/pydantic-for-fastapi/>
VANCOUVER
Amal Shaji | Sciencx - » Pydantic for FastAPI. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/05/28/pydantic-for-fastapi/
CHICAGO
" » Pydantic for FastAPI." Amal Shaji | Sciencx - Accessed . https://www.scien.cx/2021/05/28/pydantic-for-fastapi/
IEEE
" » Pydantic for FastAPI." Amal Shaji | Sciencx [Online]. Available: https://www.scien.cx/2021/05/28/pydantic-for-fastapi/. [Accessed: ]
rf:citation
» Pydantic for FastAPI | Amal Shaji | Sciencx | https://www.scien.cx/2021/05/28/pydantic-for-fastapi/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.