You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI如何将多个图片URL以列表形式存入PostgreSQL数据库

问题场景

使用FastAPI实现多图片上传功能时,图片可正常保存到服务器静态目录,但数据库仅存储最后一张图片的访问URL,无法将所有图片URL以列表形式存入PostgreSQL对应表的img字段。
当前代码存在的核心问题:

  • 文件写入循环中,存储文件路径的变量每次迭代都会被覆盖,循环结束后仅保留最后一个文件的路径
  • SQLAlchemy模型的img字段定义为普通字符串类型,不支持数组格式存储
  • Pydantic返回模型的img字段定义为字符串类型,与列表格式不匹配
  • 接口构造Product实例时使用了imgs_url字段名,与模型定义的img字段名不一致,存在参数错误
  • 异常处理直接返回普通字典,不符合接口响应模型定义,会触发序列化错误
  • 未提前判断存储目录是否存在,目录缺失时会触发文件写入错误
实现方案

1. 调整SQLAlchemy模型

PostgreSQL原生支持数组类型,直接使用SQLAlchemy提供的ARRAY类型存储URL列表,同时补全模型缺失的字段定义:

from sqlalchemy import Column, String, Text, Float
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.orm import relationship

class Product(Base):
    __tablename__ = "products"
    name = Column(String, nullable=False)
    price = Column(Float, nullable=False)
    description = Column(Text, nullable=False)
    owner = relationship("Vendor", back_populates="product")
    img = Column(ARRAY(String), nullable=False)

注意:修改模型结构后需要执行数据库迁移,同步表结构变更。

2. 调整Pydantic响应模型

将img字段类型修改为字符串列表,匹配数据库存储格式:

from pydantic import BaseModel
from typing import List

class ProductBase(BaseModel):
    name: str
    price: float
    description: str

class ShowProduct(ProductBase):
    img: List[str]

    class Config:
        orm_mode = True

3. 修正上传接口逻辑

初始化空列表收集所有文件的访问URL,循环写入文件时逐个拼接URL加入列表,修正字段名、异常处理、路径拼接等问题:

import os
from fastapi import APIRouter, Form, File, UploadFile, Depends, status, HTTPException
from sqlalchemy.orm import Session
from typing import List

# 提前定义常量,不要放在循环内重复赋值
FILEPATH = "./static/product_images/"
# 服务访问地址,生产环境替换为实际域名
SERVER_HOST = "http://localhost:8000"

@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),
):
    # 自动创建存储目录,已存在时不报错
    os.makedirs(FILEPATH, exist_ok=True)
    file_urls = []

    for file in files:
        try:
            # 生成唯一存储文件名
            save_filename = imghex(file.filename)
            save_full_path = os.path.join(FILEPATH, save_filename)
            # 写入文件到服务器
            contents = await file.read()
            with open(save_full_path, 'wb') as f:
                f.write(contents)
            # 拼接可访问的URL,加入列表
            access_url = f"{SERVER_HOST}/static/product_images/{save_filename}"
            file_urls.append(access_url)
        except Exception:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="File upload failed"
            )
        finally:
            await file.close()

    # 构造数据库记录,字段名与模型保持一致
    new_product = Product(
        name=name,
        price=price,
        description=description,
        img=file_urls
    )

    db.add(new_product)
    db.commit()
    db.refresh(new_product)
    return new_product

4. 配置静态文件访问

确保FastAPI主应用已挂载静态文件目录,否则拼接的图片URL无法正常访问:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()
# 挂载静态资源目录
app.mount("/static", StaticFiles(directory="static"), name="static")
验证效果

完成上述修改后,上传多张图片时,所有图片的访问URL会按顺序存入PostgreSQL的img数组字段,接口返回结果也会以列表形式展示所有图片地址,符合预期存储要求。

内容的提问来源于stack exchange,提问作者pythonGo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:39:19