Home > database >  Fastapi how to convert string to list when calling get methos?
Fastapi how to convert string to list when calling get methos?

Time:01-30

I am using mysql database and it's doesn't support list if I stored sting like "apple","banana" in my mysql database then when using get method fastapi how to convert theme from string to list like ["apple","banana"]. I tried this but didn't work and also not getting the image fields until I remove @property.

class Shop_page(BaseModel):
      product_title: str
      product_image: str
      class Config():
          orm_mode = True
      @property
      def product_image(self):
        return self.product_image.split(",")

here is my get method

@router.get("/shop_page", response_model=List[schemas.Shop_page],status_code=status.HTTP_200_OK)
async def create_variations(db: Session = Depends(get_db)):
          parent_item = db.query(models.ParentProduct).all()
          return parent_item

my result look like now

[
  {
    "product_title": "DEMO PRODUCT",
    "product_image": "image1_url,image2_url"
  }
]

my expected result will be look like this

[
      {
        "product_title": "DEMO PRODUCT",
        "product_image": ["image1_url,image2_url"]
      }
    ]

CodePudding user response:

Pydantic does not support @property decorator serializing

And I think you can just override from_orm method as follows:

from typing import Type, Any

from pydantic import BaseModel, validator


class ShopPage(BaseModel):
    product_title: str
    product_image: list

    class Config:
        orm_mode = True

    def from_orm(cls: Type['Model'], obj: Any):
        if hasattr(obj, "product_image") and isinstance(obj.product_image, str):
            obj.product_image = obj.product_image.split(",")

        return super().from_orm(obj)

CodePudding user response:

This is what validators are for. But you need to define the schema the way you actually want it, not the way you receive it from your ORM. That means product_image should be annotated as a list[str] and your validator with pre=True will handle the case, if you try and initialize it with a string instead:

from pydantic import BaseModel, validator


class ShopPage(BaseModel):
    product_title: str
    product_image: list[str]

    class Config:
        orm_mode = True

    @validator("product_image", pre=True)
    def split_urls(cls, v: object) -> object:
        if isinstance(v, str):
            return v.split(",")
        return v


if __name__ == "__main__":
    class TestORM:
        product_title = "foo"
        product_image = "bar,baz"

    obj = ShopPage.from_orm(TestORM)
    print(obj.json(indent=2))

Output:

{
  "product_title": "foo",
  "product_image": [
    "bar",
    "baz"
  ]
}

The advantage of the validator approach is that it will apply regardless of how you initialize ShopPage and can even apply during assignment, if you configure your model with validate_assignment = True. So even if you do ShopPage(product_title="a", product_image="b,c"), you'll get the product_image as a list.

  • Related