What's the canonical way to add a custom method to a model class? #653
-
First Check
Commit to Help
Example Code# model.py (simplified)
class PersonBase(SQLModel):
first_name: str
last_name: str
name_suffix: Optional[str] = None
nickname: Optional[str] = None
def full_name(self) -> str:
full_name = f"{self.first_name} {self.last_name}"
if self.name_suffix:
if self.name_suffix in ["II", "III", "IV"]:
full_name = f"{full_name} {self.name_suffix}"
else:
full_name = f"{full_name}, {self.name_suffix}"
return full_name
class Person(PersonBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
class PersonCreate(PersonBase):
pass
class PersonRead(PersonBase):
id: int
full_name: str
class PersonUpdate(SQLModel):
first_name: Optional[str] = None
last_name: Optional[str] = None
name_suffix: Optional[str] = None
nickname: Optional[str] = None
# Person routers
router = APIRouter(
prefix="/persons",
tags=["persons"],
responses={404: {"description": "Not found"}},
)
@router.post("/", response_model=PersonRead)
def create_person(*, session: Session = Depends(get_session), person: Person):
person = Person.from_orm(person)
session.add(person)
session.commit()
session.refresh(person)
return person
@router.get("/", response_model=List[PersonRead])
def read_persons(
*,
session: Session = Depends(get_session),
offset: int = 0,
limit: int = Query(default=100, lte=100)
):
persons = session.exec(select(Person).offset(offset).limit(limit)).all()
return persons
# TODO: Get endpoint to return a value for the full_name method
@router.get("/{person_id}", response_model=PersonRead)
def read_person(*, session: Session = Depends(get_session), person_id: int):
person = session.get(Person, person_id)
if not person:
raise HTTPException(status_code=404, detail="Person not found")
full_name = person.full_name()
person_dict = person.__dict__
person_dict["full_name"] = full_name
return PersonRead(**person_dict)
@router.delete("/{person_id}")
def delete_person(*, session: Session = Depends(get_session), person_id: int):
person = session.get(Person, person_id)
if not person:
raise HTTPException(status_code=404, detail="Person not found")
session.delete(person)
session.commit()
return {"ok": True} DescriptionIn addition to the fields defined in my For example, a request for
With the code above, I get the following Traceback:
Operating SystemOther Operating System DetailsRunning in a Docker container on macOS. SQLModel Version0.0.8 Python Version3.12.0 Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
It's actually a property, so you should use a And the error is because you have shadowed the |
Beta Was this translation helpful? Give feedback.
-
Thanks so much, @wojciech-mazur-mlg. So I guess the bigger question is whether this is a good practice? It seems like this would be a convenient place to build out a few convenience methods that would be annoying for someone to do on the client side. Is there a different approach that would be a better long-term practice? |
Beta Was this translation helpful? Give feedback.
-
It seems that I have this working now. The URL
|
Beta Was this translation helpful? Give feedback.
It's actually a property, so you should use a
@property
decorator onfull_name
method.And the error is because you have shadowed the
full_name
attribute. You can removefull_name
fromPersonRead
class.