5

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)
Jekson
  • 2,892
  • 8
  • 44
  • 79

1 Answers1

0

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.

lsabi
  • 3,641
  • 1
  • 14
  • 26
  • How to update profile image using above concept ? I have asked in this" https://stackoverflow.com/questions/64474061/how-to-update-file-in-crud-operation-using-fastapi-and-mongodb – Himal Acharya Oct 22 '20 at 02:52
  • @HimalAcharya your question is not related to this one, as you are using a nosql (schemaless) database instead of a relational one. SQLAlchemy won't work and is therefore outside of this question's topic – lsabi Oct 22 '20 at 12:27
  • I applied above logic accordingly in my project for adding student (it worked). I just want to know how to update file in the above example using SQLAlchemy ,CRUD operation only – Himal Acharya Oct 22 '20 at 12:40
  • In this case the image is uploaded to a static server. You'll have to update the image and the data atomically. In the database there will only be the reference of the file name and type, while the actual image will be stored in the static server – lsabi Oct 22 '20 at 14:28
  • Can i get a update operation code for above example? While I apply above logic, everytime it gives parsing error in body. – Himal Acharya Oct 22 '20 at 23:39