Fastapi: [QUESTION]How can I save and return image url path properly ?

Created on 25 May 2020  Â·  2Comments  Â·  Source: tiangolo/fastapi

First check

  • [ √ ] I used the GitHub search to find a similar issue and didn't find it.
  • [ √ ] I searched the FastAPI documentation, with the integrated search.
  • [ √ ] I already searched in Google "How to X in FastAPI" and didn't find any information.

Description

How can I save and return image url path properly ?

I define a peewee model like this:

class Image(peewee.Model):

    name = peewee.CharField()
    url = peewee.CharField()

    class Meta:
        database = db

I define a pydantic model like this:

class ImageModel(BaseModel):
    id: int
    name: str
    url: str

    class Config:
        orm_mode = True
        getter_dict = PeeweeGetterDict

I save the file like this and success:

cwd_path = Path.cwd() / "static"

def save_upload_file_tmp(upload_file: UploadFile, destination: Path) -> Path:
    try:
        suffix = Path(upload_file.filename).suffix
        with NamedTemporaryFile(delete=False, suffix=suffix, dir=destination) as tmp:
            shutil.copyfileobj(upload_file.file, tmp)
            tmp_path = Path(tmp.name)
            Image.get_or_create(name=tmp_path.name, url=tmp_path)
    finally:
        upload_file.file.close()
    return tmp_path

@app.post("/files/")
async def create_tmp_file(files: List[UploadFile] = File(...)):
    dest = cwd_path
    image_list = []
    for file in files:
        f = save_upload_file_tmp(file, dest)
        image_list.append(f)
    return image_list

I found there is something wrong if I save the url with the path. I can't return the url directly, but when I use Fileresponse, it's a object, not a url string.

Is it possible to save the PATH in database and return it to the frontend ?

If I want to query for multiple data, is it possible to use response_model ?


I found a way but is it the right way ?

  1. I mount the "static";
  2. I write a HARD CODE like this:
@app.get("/images", response_model=List[ImageModel])
async def get_images():
    image_list = Image.select()
    for i in image_list:
        i.url = "http://127.0.0.1:8000/static/" + i.name
    return list(image_list)

It works...But is there any better way to do? THX.

answered question

Most helpful comment

thanks @tiangolo .
I have check the starlette.request.url_for(). I think this function can solve that problem.
so I close this.

All 2 comments

First, about Peewee, it is not designed for modern Python, please check all the caveats: https://fastapi.tiangolo.com/advanced/sql-databases-peewee/

About your question, it seems to me like you are storing the file in a temporary directory and then saving that path in the DB.

If you store the file in a temporary directory it will be deleted afterwards, you have to store it in a predefined location that is not later removed.

If you still have problems, please create a minimal self-contained example that shows your use case, that way I (or someone else) can take a look.

thanks @tiangolo .
I have check the starlette.request.url_for(). I think this function can solve that problem.
so I close this.

Was this page helpful?
0 / 5 - 0 ratings