Reputation: 413
I'm using fast-api and pydantic for modeling in my project, I created a function convert the attributes to dictionary.
from pydantic import BaseModel
class WidgetItem(BaseModel):
"""Class for WidgetItem"""
adId: str = ''
@classmethod
def generate_widget_item_dict(cls):
return {
'adId': cls.adId
}
Im trying to call generate_widget_item_dict() but I got this error:
AttributeError: type object 'WidgetItem' has no attribute 'adId'
Upvotes: -1
Views: 1907
Reputation: 12008
In the case where you want only some of the attributes of a given class, I would create multiple classes and return the correctly "masked" class. Here's an example to illustrate:
Note: This can get tricky when you have lots of dependencies.
from pydantic import BaseModel
class WidgetItem1(BaseModel):
"""
Class for WidgetItem
Note: this class only has 1 attribute
"""
attr_1: str = 'one'
class WidgetItem2(WidgetItem1):
"""
A more granular class for WidgetItem ->
Inherited from `WidgetItem1`
Note: this class has 3 attributes
"""
attr_2: str = 'two'
attr_3: str = 'three'
Given a fastapi endpoint, you can choose to return
specific attributes, depending on your response_model
:
WidgetItem1
: will return only attr_1
WidgetItem2
: will return 3 attributes: attr_1
, attr_2
, attr_3
Here's some code to demonstrate:# Choose the response model you want to return
from fastapi import FastAPI
app = FastAPI()
# Create a function to use for multiple endpoints
def get_widget():
"""
Returns a dummy widget to demonstrate
functionality. Change the `response_model` to
see different attributes returned.
"""
# Initially set all 3 attributes and see
# which are returned by fastapi based on `response_model`
result = {
"attr_1": "one",
"attr_2": "two",
"attr_3": "three"
}
return result
@app.get("/widgets-1", response_model=WidgetItem1)
def get_widget_1():
"""
Endpoint which wraps `get_widget()`
with `WidgetItem1` as the response model
"""
return get_widget()
@app.get("/widgets-2", response_model=WidgetItem2)
def get_widget_2():
"""
Endpoint which wraps `get_widget()`
with `WidgetItem2` as the response model
"""
return get_widget()
Alternatively, you can go ahead and create custom functionality to return a specifically formatted dictionary. If this is the case, the other answers should work for you.
Upvotes: 1
Reputation: 290
It happens since WidgetItem
should be initiated since it inherits from BaseModel
.
This is different than for instance:
class WidgetModel:
adId: str = ""
@classmethod
def generate_widget_item_dict(cls):
return {
'adId': cls.adId
}
In such a case it will work. However this is not a Pydantic model.
If you want to create a dict from a Pydantic model you can just do:
from pydantic import BaseModel
class WidgetItem(BaseModel):
"""Class for WidgetItem"""
adId: str
w = WidgetItem(adId="id")
w.dict()
Upvotes: 2