I deal with FastAPI and can't figure out how to make simple (from the point of view of my experience with django) thing - add a product with an image to the database. As I understood it, the image should be stored in a static folder and only a link to it should be stored in the database. Based on the information from the official documentation, I have added this scheme
schema.py
from pydantic import BaseModel, HttpUrl
from typing import Optional
class ProductImageSchema(BaseModel):
url: HttpUrl
name: str
class ProductSchema(BaseModel):
name: str
description: Optional[str] = None
image: Optional[ProductImage] = None
I'm using SQLAlchemy. Now the first question I have is how to properly describe the product model. models.py
product = Product(
"product",
metadata,
Column("id", Integer, primary_key=True),
Column("name", String(50)),
Column("description", String(50)),
Column(....str_or_url..????) # field with relation with image,
)
And it is not clear how to create new instances of the product object. Something like...
crud.py
async def post(payload: ProductSchema, file: UploadFile = File(...)):
content = await file.read()
if file.content_type not in ['image/jpeg', 'image/png']:
raise HTTPException(status_code=406, detail="Only .jpeg or .png files allowed")
file_name = f'{uuid.uuid4().hex}{ext}'
async with aiofiles.open(file_name, "wb") as f:
await f.write(content)
query = product.insert().values(title=payload.name, description=payload.description, image=????????)
return await database.execute(query=query)
Your approach is correct. As far as I know, images, as well as other user's files, are stored in a static (or whatever) folder and a reference is kept in the database. In some cases the file name (possibly with the extension) is stored in the table, while in other cases, especially in a more distributed app, the entire URL is stored.
Your crud.py file seems to be correct. Just change the image parameter in the query to either the URL or the filename that you used. Be sure to check that no other user has already inserted a file with the same name (and extension), or you'll overwrite your user's files!
Going back to your questions,
I would further improve the ProductImageSchema in the schema.py file with the following
from datetime import datetime
class ProductImageSchema(BaseModel):
url: HttpUrl
name: str
type: str
creation_date: datetime.datetime = datetime.now()
Since you haven't specified the data model (i.e. the database structure), I can only infer from what you have written. If my infer is correct, a product may have multiple images, so you'll need a table for the product and one for the images. My guess is that images are not shared between products, otherwise you'll need 3 tables.
Although the piece of code does not look much like valid SQLAlchemy code, here is an example of what you could do
product = Product(
"product",
metadata,
Column("id", Integer, primary_key=True),
Column("name", String(50)),
Column("description", String(50))
)
images = Image(
"image",
metadata,
Column("product", Integer, ForeignKey(Product.id), primary_key=True,),
Column("name", String(50), primary_key=True),
Column("filetype", String(50))
)
But I'm not sure this is valid SQLAlchemy code since what you posted does not look right as well. Anyways, I hope it is enough to get the idea.