like I used to do with FastApi routes, I want to make a function that is expecting a dict. I want to type hint like in FastAPI with a pydantic model.
Note that I am just using FastAPI as a reference here and this app serves a total different purpose.
What I did:
models.py
from pydantic import BaseModel
class Mymodel(BaseModel):
name:str
age:int
main.py
def myfunc(m:Mymodel):
print(m)
print(m.name)
myfunc({"name":"abcd","age":3})
It prints m as a normal dict and not Mymodel and m.name just throws an AttributeError.
I don't understand why it is behaving like this because the same code would work in FastAPI. Am I missing something here? What should I do to make this work.
I am expecting a dict arg in the func, I want to type hint with a class inherited from pydantic BaseModel. Then I want to acccess the attributes of that class.
I don't want to do:
def myfunc(m):
m = Mymodel(**m)
Thank You.
Since you pass a dict to the function, the attribute should be accessed in the following way:
print(m['name'])
Otherwise, to use m.name instead, you need to convert the dict to the corresponding Pydantic model before passing it to the function, as shwon below:
data = {"name":"abcd", "age":3}
myfunc(Mymodel(**data))
# or
myfunc(Mymodel.parse_obj(data))
The reason that passing {"name":"abcd", "age":3} in FastAPI and later accessing the attributes using the dot operator (e.g., m.name) works, is that FastAPI does the above conversion internally, as soon as a request arrives. That is why you can then convert it back to a dictionary in your endpoint, using m.dict(). Try, for example, passing an incorrect key, e.g., data = {"name":"abcd","myage":3} myfunc(Mymodel(**data)). You would get a field required (type=value_error.missing) error (as part of Pydantic's Error Handling), similar to what FastAPI would return (as shown below) if a similar request attempted to go through (you could test that through OpenAPI at http://127.0.0.1:8000/docs). Otherwise, any dictionary passed by the user (in the way you show in the question) would go through without throwing an error, in case it didn't match the Pydantic model.
{
"detail": [
{
"loc": [
"body",
"age"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}