update
This commit is contained in:
parent
c79cf5186c
commit
b2b7770de2
@ -137,11 +137,6 @@ async def read_clothes_by_category(
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""根据分类获取衣服"""
|
||||
# 检查分类是否存在
|
||||
category = await clothing_service.get_category(db, category_id=category_id)
|
||||
if category is None:
|
||||
raise BusinessError("分类不存在", code=404)
|
||||
|
||||
clothes = await clothing_service.get_clothes_by_category(
|
||||
db=db,
|
||||
category_id=category_id,
|
||||
@ -151,46 +146,6 @@ async def read_clothes_by_category(
|
||||
# 手动返回标准响应格式
|
||||
return StandardResponse(code=200, data=[Clothing.model_validate(clothing) for clothing in clothes])
|
||||
|
||||
@router.get("/{clothing_id}", tags=["clothing"])
|
||||
async def read_clothing(
|
||||
clothing_id: int,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""获取单个衣服"""
|
||||
clothing = await clothing_service.get_clothing(db, clothing_id=clothing_id)
|
||||
if clothing is None:
|
||||
raise BusinessError("衣服不存在", code=404)
|
||||
# 手动返回标准响应格式
|
||||
return StandardResponse(code=200, data=Clothing.model_validate(clothing))
|
||||
|
||||
@router.put("/{clothing_id}", tags=["clothing"])
|
||||
async def update_clothing(
|
||||
clothing_id: int,
|
||||
clothing: ClothingUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: UserModel = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
更新衣服
|
||||
|
||||
需要JWT令牌认证
|
||||
"""
|
||||
# 检查分类是否存在
|
||||
if clothing.clothing_category_id is not None:
|
||||
category = await clothing_service.get_category(db, category_id=clothing.clothing_category_id)
|
||||
if category is None:
|
||||
raise BusinessError("指定的分类不存在", code=404)
|
||||
|
||||
clothing = await clothing_service.update_clothing(
|
||||
db=db,
|
||||
clothing_id=clothing_id,
|
||||
clothing_update=clothing
|
||||
)
|
||||
if clothing is None:
|
||||
raise BusinessError("衣服不存在", code=404)
|
||||
# 手动返回标准响应格式
|
||||
return StandardResponse(code=200, data=Clothing.model_validate(clothing))
|
||||
|
||||
@router.delete("/{clothing_id}", tags=["clothing"])
|
||||
async def delete_clothing(
|
||||
clothing_id: int,
|
||||
|
||||
70
app/api/v1/tryon.py
Normal file
70
app/api/v1/tryon.py
Normal file
@ -0,0 +1,70 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Response
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
import logging
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from app.api import deps
|
||||
from app.core import security
|
||||
from app.core.config import settings
|
||||
from app.schemas.tryon import TryonRequest
|
||||
from app.schemas.user import User
|
||||
from app.services import person_image as person_image_service
|
||||
from app.services import clothing as clothing_service
|
||||
from app.api.deps import get_current_user
|
||||
from app.services.dashscope_service import DashScopeService
|
||||
from app.schemas.response import StandardResponse
|
||||
from app.models.tryon import TryonHistory
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/tryon", tags=["tryon"])
|
||||
async def tryon(
|
||||
tryon_request: TryonRequest,
|
||||
db: AsyncSession = Depends(deps.get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
# 获取当前用户的默认形象
|
||||
person_image = await person_image_service.get_default_image(db, current_user.id)
|
||||
if not person_image:
|
||||
raise HTTPException(status_code=404, detail="默认形象不存在")
|
||||
|
||||
# 获取试穿请求中的衣物ID
|
||||
top_clothing_id = tryon_request.top_clothing_id
|
||||
bottom_clothing_id = tryon_request.bottom_clothing_id
|
||||
|
||||
# 获取衣物详情
|
||||
top_clothing_url = tryon_request.top_clothing_url
|
||||
bottom_clothing_url = tryon_request.bottom_clothing_url
|
||||
|
||||
if top_clothing_id:
|
||||
top_clothing = await clothing_service.get_clothing(db, top_clothing_id)
|
||||
top_clothing_url = top_clothing.image_url
|
||||
|
||||
if bottom_clothing_id:
|
||||
bottom_clothing = await clothing_service.get_clothing(db, bottom_clothing_id)
|
||||
bottom_clothing_url = bottom_clothing.image_url
|
||||
|
||||
|
||||
# 调用试穿服务
|
||||
dashscope_service = DashScopeService()
|
||||
tryon_result = await dashscope_service.generate_tryon(person_image.image_url,
|
||||
top_clothing_url,
|
||||
bottom_clothing_url)
|
||||
|
||||
task_id = tryon_result.get("task_id")
|
||||
if task_id:
|
||||
tryon_history = TryonHistory(
|
||||
user_id=current_user.id,
|
||||
person_image_id=person_image.id,
|
||||
top_clothing_id=top_clothing_id,
|
||||
bottom_clothing_id=bottom_clothing_id,
|
||||
top_clothing_url=top_clothing_url,
|
||||
bottom_clothing_url=bottom_clothing_url,
|
||||
task_id=task_id
|
||||
)
|
||||
db.add(tryon_history)
|
||||
await db.commit()
|
||||
return StandardResponse(code=200, message="试穿任务已提交", data=tryon_history.id)
|
||||
else:
|
||||
return StandardResponse(code=500, message="试穿任务提交失败")
|
||||
@ -3,6 +3,7 @@ from app.db.database import Base, engine
|
||||
from app.models.users import User
|
||||
from app.models.person_images import PersonImage
|
||||
from app.models.clothing import ClothingCategory, Clothing
|
||||
from app.models.tryon import TryonHistory
|
||||
|
||||
# 创建所有表格
|
||||
async def init_db():
|
||||
|
||||
37
app/models/tryon.py
Normal file
37
app/models/tryon.py
Normal file
@ -0,0 +1,37 @@
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Enum
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.db.database import Base
|
||||
import enum
|
||||
|
||||
class TryonStatus(enum.Enum):
|
||||
"""试穿状态枚举"""
|
||||
GENERATING = "生成中"
|
||||
COMPLETED = "已生成"
|
||||
FAILED = "失败"
|
||||
|
||||
class TryonHistory(Base):
|
||||
"""试穿记录数据模型"""
|
||||
__tablename__ = "tryon_history"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True, comment="用户ID")
|
||||
person_image_id = Column(Integer, ForeignKey("person_images.id"), nullable=False, index=True, comment="人物形象ID")
|
||||
top_clothing_id = Column(Integer, ForeignKey("clothing.id"), nullable=True, comment="上衣ID")
|
||||
bottom_clothing_id = Column(Integer, ForeignKey("clothing.id"), nullable=True, comment="下装ID")
|
||||
top_clothing_url = Column(String(500), nullable=True, comment="上衣图片URL")
|
||||
bottom_clothing_url = Column(String(500), nullable=True, comment="下装图片URL")
|
||||
task_id = Column(String(100), nullable=True, index=True, comment="任务ID")
|
||||
completion_url = Column(String(500), nullable=True, comment="生成结果URL")
|
||||
status = Column(Enum(TryonStatus), default=TryonStatus.GENERATING, comment="状态")
|
||||
create_time = Column(DateTime, default=func.now(), comment="创建时间")
|
||||
update_time = Column(DateTime, default=func.now(), onupdate=func.now(), comment="更新时间")
|
||||
|
||||
# 关系
|
||||
user = relationship("User", backref="tryon_histories")
|
||||
person_image = relationship("PersonImage", backref="tryon_histories")
|
||||
top_clothing = relationship("Clothing", foreign_keys=[top_clothing_id], backref="top_tryon_histories")
|
||||
bottom_clothing = relationship("Clothing", foreign_keys=[bottom_clothing_id], backref="bottom_tryon_histories")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<TryonHistory(id={self.id}, status={self.status.name})>"
|
||||
@ -18,6 +18,7 @@ class User(Base):
|
||||
# 关系
|
||||
person_images = relationship("PersonImage", back_populates="user", cascade="all, delete-orphan")
|
||||
clothings = relationship("Clothing", back_populates="user", cascade="all, delete-orphan")
|
||||
# tryon_histories已通过backref在TryonHistory模型中定义
|
||||
|
||||
def __repr__(self):
|
||||
return f"<User(id={self.id}, nickname={self.nickname})>"
|
||||
|
||||
9
app/schemas/tryon.py
Normal file
9
app/schemas/tryon.py
Normal file
@ -0,0 +1,9 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class TryonRequest(BaseModel):
|
||||
top_clothing_id: Optional[int] = None
|
||||
bottom_clothing_id: Optional[int] = None
|
||||
top_clothing_url: Optional[str] = None
|
||||
bottom_clothing_url: Optional[str] = None
|
||||
Loading…
Reference in New Issue
Block a user