Field validator - dantico
Description: Tools to convert Django ORM models to Pydantic models

Skip to content

# Field validator

Custom validation is not an easy task in this case. But we still can achieve it by using threads.

Because we define a validator to validate fields on inheriting models, we should set `check_fields=False` on the validator. More information can be found here.

    # schemas.py

    import asyncio
    import concurrent.futures

    from asgiref.sync import sync_to_async
    from dantico import ModelSchema
    from pydantic import validator

    from users.models import User

    class UserSchema(ModelSchema):
        class Config:
            model = User
            exclude = ["password"]

        @validator("username", check_fields=False)
        def validate_username(cls, v):
            """
            Here we are using async method as validator. Because there is
            already an event loop (using FastAPI), we need to start another thread.

            :param cls: Access the class of the object that is being validated
            :param v: Validate the value
            :return: The result of the username_must_be_unique function
            """

            @sync_to_async
            def username_must_be_unique():
                if User.objects.filter(username__icontains=v).exists():
                    raise ValueError("username already exists")
                return v

            # A way to run async code in a sync environment.
            pool = concurrent.futures.ThreadPoolExecutor(1)
            result = pool.submit(asyncio.run, username_must_be_unique()).result()

            return result