0

I have a pydantic model for request like below,

from pydantic import BaseModel, Field
from typing import List, ClassVar
from fastapi import FastAPI


app = FastAPI()


class myRequestModel(BaseModel):
   items: List[str] = Field(..., example=['a','b'])
   n: int = Field(100, example=50, gt=0)


@app.post("/test")
def test_func(args: myRequestModel):
   dynamic_threshold = my_func(...)     # let say dynamic_threshold is determined at runtime
   
   if args.n < dynamic_threshold:
      args.n = 100                      # I want to assign args.n only when it is under dynamic_threshold

When users do not give n, it is automatically set to 100 which is default value through Field attribute.

If users give n less than dynamic_threshold, it needs to be set to default value.

In order to achieve this, I tried to add _default_n using typing.ClassVar. See below,

class myRequestModel(BaseModel):
   _default_n: ClassVar[int] = 100
   n: int = Field(_default_n, example=100, gt=0)
   ...

   class Config:
      underscore_attrs_are_private = True


@app.post("/test")
def test_func(args: myRequestModel):
   ...
   
   if args.n < dynamic_threshold:
      args.n = args._default_n      <-- Here, I get a warning 'Access to a protected member _default_n of a class

This works, but I don't think this is not a right way for warning..

What is the appropriate way to make default value that can be used at runtime?

cointreau
  • 864
  • 1
  • 10
  • 21
  • 1
    How about using a validation method / root validator to clamp the value inside your model? That will keep all the logic out of your view: https://pydantic-docs.helpmanual.io/usage/validators/ - the value you return will be the actual value – MatsLindh Feb 16 '22 at 10:10
  • Thank you for the comment. I think validator can do it, though it seems there are some conditions if I want to pass dynamic_threshold value to the validator method to compare two values(dynamic_threshold and n, if I want to use validator I think it needs to be compare inside the model). Instead of that, I decided to keep _default_n as ClassVar and just add simple set method in my model. So if some value comes inside the post method, I can compare args.n to threshold and just call set method in the model if n should be default value. – cointreau Feb 16 '22 at 23:25

0 Answers0