Using the fastAPI multiple uploads function, i am trying to upload images to my server and save the urls as a list to my postgres database. Here is the code i am using to upload the image:
@router.post('/addProductFD', status_code=status.HTTP_201_CREATED, response_model=ShowProduct)
async def create(
name: str = Form(...),
price: float = Form(...),
description: str = Form(...),
files: List[UploadFile] = File(...),
db: Session = Depends(get_db),
):
for file in files:
try:
FILEPATH = "./static/product_images/"
pimage_name = FILEPATH imghex(file.filename)
contents = await file.read()
with open(pimage_name, 'wb') as f:
f.write(contents)
except Exception:
return {"message": "There was an error uploading the file(s)"}
finally:
await file.close()
file_urls = "localhost:8000" pimage_name[1:]
new_item = Product(
name=name,
price=price,
description=description,
imgs_url=file_urls,
)
db.add(new_item)
db.commit()
db.refresh(new_item)
{"filenames": [file.filename for file in files]}
return new_item
When i run this code, it uploads the images and adds the url of just the first image to my database. Please how do i make this code to add the image urls to my database as a list. Here is an example of what i want to do:
Below is the schemas.ShowProduct:
class ShowProduct(ProductBase):
name: str
description: str
img: str
class Config():
orm_mode = True
Below is my postgresDB models.product:
class Product(Base):
name = Column(String, nullable=False)
description = Column(Text, nullable=False)
owner = relationship("Vendor", back_populates="product")
img = Column(String)
So i want to recieve a list of the imageurls and add it to the img database column:
Please help!
CodePudding user response:
At first, you need to alter your db model:
class Product(Base):
name = Column(String, nullable=False)
description = Column(Text, nullable=False)
owner = relationship("Vendor", back_populates="product")
imgs_url = Column(ARRAY(String))
Note: do not forget to generate and apply migration.
then simply pass imgs_url
as a list
to Product
initializer:
new_item = Product(
name=name,
price=price,
description=description,
imgs_url=["url1", "url2"],
)
Finally, you can alter your model factory:
class ShowProduct(ProductBase):
name: str
description: str
imgs_url: list[str]
class Config:
orm_mode = True
I think you should rethink your design and take imho better approach, with table relationships. So you would create two tables: products
(as already defined) and images
(new one) which will be connected via foreign key:
class Product(Base):
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
description = Column(Text, nullable=False)
owner = relationship("Vendor", back_populates="product")
images = relationship("Image", back_populates="product")
class Image(Base):
url = Column(String, nullable=False)
product_id = Column(Integer, ForeignKey("images.id"))
product = relationship("Product", back_populates="images")
CodePudding user response:
You need to join the urls in the for-loop.
first make an empty array to store the file urls, then in the for loop append to it. Then finally use join to concatenate the strings with commas to give you a string with comma separated items
fileList = []
for file in files:
try:
FILEPATH = "./static/product_images/"
pimage_name = FILEPATH imghex(file.filename)
contents = await file.read()
with open(pimage_name, 'wb') as f:
f.write(contents)
except Exception:
return {"message": "There was an error uploading the file(s)"}
finally:
await file.close()
fileList.append("localhost:8000" pimage_name[1:])
file_urls = ",".join(fileList)