Home > Software engineering >  FastAPI Optional validator
FastAPI Optional validator

Time:11-16

I write some API with Student model, for update it - I use another model StudentUpdateIn. On Student model I have validator ( gt = 15 ). But how I can apply this validator to StudentUpdateIn too?

I found way with using @validator, but I think it is not the way, that I should use on my code.

Originally was chosen incorrect pattern....

class StudentUpdateIn(BaseModel):
    first_name: Optional[str]
    last_name: Optional[str]
    age: Optional[int]
    group: Optional[str]

    @validator('age')
    def greater_than(cls, v):
        if not v > 15:
            raise ValueError("Age must be greater than 15")


class StudentIn(BaseModel):
    first_name: str = Field(..., max_length=30)
    last_name: str = Field(..., max_length=30)
    age: int = Field(..., gt=15)
    group: str = Field(..., max_length=10)

CodePudding user response:

I am pretty sure there is no non-hacky way of doing it, but if you dont mind to have some introspection in code, here is the decorator which takes field names and internally mark pydantic fields as not required (optional):

import inspect

def optional(*fields):
    def dec(_cls):
        for field in fields:
            _cls.__fields__[field].required = False
        return _cls

    if fields and inspect.isclass(fields[0]) and issubclass(fields[0], BaseModel):
        cls = fields[0]
        fields = cls.__fields__
        return dec(cls)
    return dec

Now you can use it to and have single class:

# you can specify optional fields - @optional("age", "group")
@optional
class StudentIn(BaseModel):
    first_name: str = Field(..., max_length=30)
    last_name: str = Field(..., max_length=30)
    age: int = Field(..., gt=15)
    group: str = Field(..., max_length=10)

or with inheritance

@optional
class StudentUpdateIn(StudentIn):
    ...
  • Related