update
This commit is contained in:
parent
16c8c11172
commit
10866b1cbb
@ -9,13 +9,14 @@ from app.services import user as user_service
|
|||||||
from app.core.security import create_access_token
|
from app.core.security import create_access_token
|
||||||
from app.db.database import get_db
|
from app.db.database import get_db
|
||||||
from app.core.exceptions import BusinessError
|
from app.core.exceptions import BusinessError
|
||||||
|
from app.schemas.response import StandardResponse
|
||||||
|
|
||||||
# 创建日志记录器
|
# 创建日志记录器
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.post("/login/wechat", response_model=LoginResponse, tags=["auth"])
|
@router.post("/login/wechat", tags=["auth"])
|
||||||
async def wechat_login(
|
async def wechat_login(
|
||||||
login_data: WechatLogin,
|
login_data: WechatLogin,
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
@ -62,7 +63,7 @@ async def wechat_login(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 返回标准响应
|
# 返回标准响应
|
||||||
return response_data
|
return StandardResponse(code=200, data=response_data)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 记录异常
|
# 记录异常
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
from fastapi import APIRouter, Depends, Query
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
@ -10,11 +10,17 @@ from app.services import clothing as clothing_service
|
|||||||
from app.db.database import get_db
|
from app.db.database import get_db
|
||||||
from app.api.deps import get_current_user
|
from app.api.deps import get_current_user
|
||||||
from app.models.users import User as UserModel
|
from app.models.users import User as UserModel
|
||||||
|
from app.core.exceptions import BusinessError
|
||||||
|
from app.schemas.response import StandardResponse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 创建日志记录器
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
# 衣服分类API
|
# 衣服分类API
|
||||||
@router.post("/categories", response_model=ClothingCategory, tags=["clothing-categories"])
|
@router.post("/categories", tags=["clothing-categories"])
|
||||||
async def create_category(
|
async def create_category(
|
||||||
category: ClothingCategoryCreate,
|
category: ClothingCategoryCreate,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@ -25,18 +31,24 @@ async def create_category(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
return await clothing_service.create_category(db=db, category=category)
|
result = await clothing_service.create_category(db=db, category=category)
|
||||||
|
logger.info(f"创建分类成功: id={result.id}, name={result.name}")
|
||||||
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/categories", response_model=List[ClothingCategory], tags=["clothing-categories"])
|
@router.get("/categories", tags=["clothing-categories"])
|
||||||
async def read_categories(
|
async def read_categories(
|
||||||
skip: int = Query(0, ge=0),
|
skip: int = Query(0, ge=0),
|
||||||
limit: int = Query(100, ge=1, le=100),
|
limit: int = Query(100, ge=1, le=100),
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""获取所有衣服分类"""
|
"""获取所有衣服分类"""
|
||||||
return await clothing_service.get_categories(db=db, skip=skip, limit=limit)
|
result = await clothing_service.get_categories(db=db, skip=skip, limit=limit)
|
||||||
|
logger.info(f"获取分类列表: 共{len(result)}条")
|
||||||
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/categories/{category_id}", response_model=ClothingCategory, tags=["clothing-categories"])
|
@router.get("/categories/{category_id}", tags=["clothing-categories"])
|
||||||
async def read_category(
|
async def read_category(
|
||||||
category_id: int,
|
category_id: int,
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
@ -44,10 +56,11 @@ async def read_category(
|
|||||||
"""获取单个衣服分类"""
|
"""获取单个衣服分类"""
|
||||||
db_category = await clothing_service.get_category(db, category_id=category_id)
|
db_category = await clothing_service.get_category(db, category_id=category_id)
|
||||||
if db_category is None:
|
if db_category is None:
|
||||||
raise HTTPException(status_code=404, detail="分类不存在")
|
raise BusinessError("分类不存在", code=404)
|
||||||
return db_category
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=db_category)
|
||||||
|
|
||||||
@router.put("/categories/{category_id}", response_model=ClothingCategory, tags=["clothing-categories"])
|
@router.put("/categories/{category_id}", tags=["clothing-categories"])
|
||||||
async def update_category(
|
async def update_category(
|
||||||
category_id: int,
|
category_id: int,
|
||||||
category: ClothingCategoryUpdate,
|
category: ClothingCategoryUpdate,
|
||||||
@ -65,10 +78,11 @@ async def update_category(
|
|||||||
category_update=category
|
category_update=category
|
||||||
)
|
)
|
||||||
if db_category is None:
|
if db_category is None:
|
||||||
raise HTTPException(status_code=404, detail="分类不存在")
|
raise BusinessError("分类不存在", code=404)
|
||||||
return db_category
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=db_category)
|
||||||
|
|
||||||
@router.delete("/categories/{category_id}", response_model=ClothingCategory, tags=["clothing-categories"])
|
@router.delete("/categories/{category_id}", tags=["clothing-categories"])
|
||||||
async def delete_category(
|
async def delete_category(
|
||||||
category_id: int,
|
category_id: int,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@ -81,11 +95,12 @@ async def delete_category(
|
|||||||
"""
|
"""
|
||||||
db_category = await clothing_service.delete_category(db=db, category_id=category_id)
|
db_category = await clothing_service.delete_category(db=db, category_id=category_id)
|
||||||
if db_category is None:
|
if db_category is None:
|
||||||
raise HTTPException(status_code=404, detail="分类不存在")
|
raise BusinessError("分类不存在", code=404)
|
||||||
return db_category
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=db_category)
|
||||||
|
|
||||||
# 衣服API
|
# 衣服API
|
||||||
@router.post("/", response_model=Clothing, tags=["clothing"])
|
@router.post("/", tags=["clothing"])
|
||||||
async def create_clothing(
|
async def create_clothing(
|
||||||
clothing: ClothingCreate,
|
clothing: ClothingCreate,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@ -99,20 +114,25 @@ async def create_clothing(
|
|||||||
# 检查分类是否存在
|
# 检查分类是否存在
|
||||||
category = await clothing_service.get_category(db, category_id=clothing.clothing_category_id)
|
category = await clothing_service.get_category(db, category_id=clothing.clothing_category_id)
|
||||||
if category is None:
|
if category is None:
|
||||||
raise HTTPException(status_code=404, detail="指定的分类不存在")
|
raise BusinessError("指定的分类不存在", code=404)
|
||||||
|
|
||||||
return await clothing_service.create_clothing(db=db, clothing=clothing)
|
result = await clothing_service.create_clothing(db=db, clothing=clothing)
|
||||||
|
logger.info(f"创建衣服成功: id={result.id}")
|
||||||
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/", response_model=List[Clothing], tags=["clothing"])
|
@router.get("/", tags=["clothing"])
|
||||||
async def read_clothes(
|
async def read_clothes(
|
||||||
skip: int = Query(0, ge=0),
|
skip: int = Query(0, ge=0),
|
||||||
limit: int = Query(100, ge=1, le=100),
|
limit: int = Query(100, ge=1, le=100),
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""获取所有衣服"""
|
"""获取所有衣服"""
|
||||||
return await clothing_service.get_clothes(db=db, skip=skip, limit=limit)
|
result = await clothing_service.get_clothes(db=db, skip=skip, limit=limit)
|
||||||
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/by-category/{category_id}", response_model=List[Clothing], tags=["clothing"])
|
@router.get("/by-category/{category_id}", tags=["clothing"])
|
||||||
async def read_clothes_by_category(
|
async def read_clothes_by_category(
|
||||||
category_id: int,
|
category_id: int,
|
||||||
skip: int = Query(0, ge=0),
|
skip: int = Query(0, ge=0),
|
||||||
@ -123,16 +143,18 @@ async def read_clothes_by_category(
|
|||||||
# 检查分类是否存在
|
# 检查分类是否存在
|
||||||
category = await clothing_service.get_category(db, category_id=category_id)
|
category = await clothing_service.get_category(db, category_id=category_id)
|
||||||
if category is None:
|
if category is None:
|
||||||
raise HTTPException(status_code=404, detail="分类不存在")
|
raise BusinessError("分类不存在", code=404)
|
||||||
|
|
||||||
return await clothing_service.get_clothes_by_category(
|
result = await clothing_service.get_clothes_by_category(
|
||||||
db=db,
|
db=db,
|
||||||
category_id=category_id,
|
category_id=category_id,
|
||||||
skip=skip,
|
skip=skip,
|
||||||
limit=limit
|
limit=limit
|
||||||
)
|
)
|
||||||
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/{clothing_id}", response_model=Clothing, tags=["clothing"])
|
@router.get("/{clothing_id}", tags=["clothing"])
|
||||||
async def read_clothing(
|
async def read_clothing(
|
||||||
clothing_id: int,
|
clothing_id: int,
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
@ -140,10 +162,11 @@ async def read_clothing(
|
|||||||
"""获取单个衣服"""
|
"""获取单个衣服"""
|
||||||
db_clothing = await clothing_service.get_clothing(db, clothing_id=clothing_id)
|
db_clothing = await clothing_service.get_clothing(db, clothing_id=clothing_id)
|
||||||
if db_clothing is None:
|
if db_clothing is None:
|
||||||
raise HTTPException(status_code=404, detail="衣服不存在")
|
raise BusinessError("衣服不存在", code=404)
|
||||||
return db_clothing
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=db_clothing)
|
||||||
|
|
||||||
@router.put("/{clothing_id}", response_model=Clothing, tags=["clothing"])
|
@router.put("/{clothing_id}", tags=["clothing"])
|
||||||
async def update_clothing(
|
async def update_clothing(
|
||||||
clothing_id: int,
|
clothing_id: int,
|
||||||
clothing: ClothingUpdate,
|
clothing: ClothingUpdate,
|
||||||
@ -159,7 +182,7 @@ async def update_clothing(
|
|||||||
if clothing.clothing_category_id is not None:
|
if clothing.clothing_category_id is not None:
|
||||||
category = await clothing_service.get_category(db, category_id=clothing.clothing_category_id)
|
category = await clothing_service.get_category(db, category_id=clothing.clothing_category_id)
|
||||||
if category is None:
|
if category is None:
|
||||||
raise HTTPException(status_code=404, detail="指定的分类不存在")
|
raise BusinessError("指定的分类不存在", code=404)
|
||||||
|
|
||||||
db_clothing = await clothing_service.update_clothing(
|
db_clothing = await clothing_service.update_clothing(
|
||||||
db=db,
|
db=db,
|
||||||
@ -167,10 +190,11 @@ async def update_clothing(
|
|||||||
clothing_update=clothing
|
clothing_update=clothing
|
||||||
)
|
)
|
||||||
if db_clothing is None:
|
if db_clothing is None:
|
||||||
raise HTTPException(status_code=404, detail="衣服不存在")
|
raise BusinessError("衣服不存在", code=404)
|
||||||
return db_clothing
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=db_clothing)
|
||||||
|
|
||||||
@router.delete("/{clothing_id}", response_model=Clothing, tags=["clothing"])
|
@router.delete("/{clothing_id}", tags=["clothing"])
|
||||||
async def delete_clothing(
|
async def delete_clothing(
|
||||||
clothing_id: int,
|
clothing_id: int,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@ -183,5 +207,6 @@ async def delete_clothing(
|
|||||||
"""
|
"""
|
||||||
db_clothing = await clothing_service.delete_clothing(db=db, clothing_id=clothing_id)
|
db_clothing = await clothing_service.delete_clothing(db=db, clothing_id=clothing_id)
|
||||||
if db_clothing is None:
|
if db_clothing is None:
|
||||||
raise HTTPException(status_code=404, detail="衣服不存在")
|
raise BusinessError("衣服不存在", code=404)
|
||||||
return db_clothing
|
# 手动返回标准响应格式
|
||||||
|
return StandardResponse(code=200, data=db_clothing)
|
||||||
@ -1,11 +1,17 @@
|
|||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException
|
||||||
|
from app.schemas.response import StandardResponse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 创建日志记录器
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get("/")
|
@router.get("/")
|
||||||
async def get_api_info():
|
async def get_api_info():
|
||||||
return {
|
api_info = {
|
||||||
"name": "美搭Meida API",
|
"name": "美搭Meida API",
|
||||||
"version": "v1",
|
"version": "v1",
|
||||||
"status": "active"
|
"status": "active"
|
||||||
}
|
}
|
||||||
|
return StandardResponse(code=200, data=api_info)
|
||||||
@ -2,17 +2,22 @@ from fastapi import APIRouter, Depends, HTTPException, Query
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from app.schemas.user_image import UserImage, UserImageCreate, UserImageUpdate
|
from app.schemas.user_image import UserImage, UserImageCreate, UserImageUpdate, UserImageWithUser
|
||||||
from app.services import user_image as user_image_service
|
from app.services import user_image as user_image_service
|
||||||
from app.db.database import get_db
|
from app.db.database import get_db
|
||||||
from app.api.deps import get_current_user
|
from app.api.deps import get_current_user
|
||||||
from app.models.users import User as UserModel
|
from app.models.users import User as UserModel
|
||||||
from app.core.exceptions import BusinessError
|
from app.core.exceptions import BusinessError
|
||||||
|
from app.schemas.response import StandardResponse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 创建日志记录器
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.post("/", response_model=UserImage, tags=["user-images"])
|
@router.post("/", tags=["user-images"])
|
||||||
async def create_image(
|
async def create_user_image(
|
||||||
image: UserImageCreate,
|
image: UserImageCreate,
|
||||||
current_user: UserModel = Depends(get_current_user),
|
current_user: UserModel = Depends(get_current_user),
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
@ -22,14 +27,14 @@ async def create_image(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
return await user_image_service.create_user_image(
|
# 设置用户ID
|
||||||
db=db,
|
image.user_id = current_user.id
|
||||||
user_id=current_user.id,
|
|
||||||
image=image
|
result = await user_image_service.create_user_image(db=db, image=image)
|
||||||
)
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/", response_model=List[UserImage], tags=["user-images"])
|
@router.get("/", tags=["user-images"])
|
||||||
async def read_images(
|
async def read_user_images(
|
||||||
skip: int = Query(0, ge=0),
|
skip: int = Query(0, ge=0),
|
||||||
limit: int = Query(100, ge=1, le=100),
|
limit: int = Query(100, ge=1, le=100),
|
||||||
current_user: UserModel = Depends(get_current_user),
|
current_user: UserModel = Depends(get_current_user),
|
||||||
@ -40,14 +45,15 @@ async def read_images(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
return await user_image_service.get_user_images(
|
images = await user_image_service.get_user_images_by_user(
|
||||||
db=db,
|
db,
|
||||||
user_id=current_user.id,
|
user_id=current_user.id,
|
||||||
skip=skip,
|
skip=skip,
|
||||||
limit=limit
|
limit=limit
|
||||||
)
|
)
|
||||||
|
return StandardResponse(code=200, data=images)
|
||||||
|
|
||||||
@router.get("/{image_id}", response_model=UserImage, tags=["user-images"])
|
@router.get("/{image_id}", tags=["user-images"])
|
||||||
async def read_image(
|
async def read_image(
|
||||||
image_id: int,
|
image_id: int,
|
||||||
current_user: UserModel = Depends(get_current_user),
|
current_user: UserModel = Depends(get_current_user),
|
||||||
@ -60,15 +66,15 @@ async def read_image(
|
|||||||
"""
|
"""
|
||||||
image = await user_image_service.get_user_image(db, image_id=image_id)
|
image = await user_image_service.get_user_image(db, image_id=image_id)
|
||||||
if image is None:
|
if image is None:
|
||||||
raise HTTPException(status_code=404, detail="图片不存在")
|
raise BusinessError("图片不存在", code=404)
|
||||||
if image.user_id != current_user.id:
|
if image.user_id != current_user.id:
|
||||||
raise HTTPException(status_code=403, detail="没有权限访问此图片")
|
raise BusinessError("没有权限访问此图片", code=403)
|
||||||
return image
|
return StandardResponse(code=200, data=image)
|
||||||
|
|
||||||
@router.put("/{image_id}", response_model=UserImage, tags=["user-images"])
|
@router.put("/{image_id}", tags=["user-images"])
|
||||||
async def update_image(
|
async def update_image(
|
||||||
image_id: int,
|
image_id: int,
|
||||||
image_update: UserImageUpdate,
|
image: UserImageUpdate,
|
||||||
current_user: UserModel = Depends(get_current_user),
|
current_user: UserModel = Depends(get_current_user),
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
):
|
):
|
||||||
@ -77,22 +83,21 @@ async def update_image(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
# 先检查图片是否存在
|
# 检查图片是否存在且属于当前用户
|
||||||
db_image = await user_image_service.get_user_image(db, image_id=image_id)
|
db_image = await user_image_service.get_user_image(db, image_id=image_id)
|
||||||
if db_image is None:
|
if db_image is None:
|
||||||
raise HTTPException(status_code=404, detail="图片不存在")
|
raise BusinessError("图片不存在", code=404)
|
||||||
if db_image.user_id != current_user.id:
|
if db_image.user_id != current_user.id:
|
||||||
raise HTTPException(status_code=403, detail="没有权限更新此图片")
|
raise BusinessError("没有权限更新此图片", code=403)
|
||||||
|
|
||||||
# 执行更新
|
|
||||||
updated_image = await user_image_service.update_user_image(
|
updated_image = await user_image_service.update_user_image(
|
||||||
db=db,
|
db=db,
|
||||||
image_id=image_id,
|
image_id=image_id,
|
||||||
image_update=image_update
|
image=image
|
||||||
)
|
)
|
||||||
return updated_image
|
return StandardResponse(code=200, data=updated_image)
|
||||||
|
|
||||||
@router.delete("/{image_id}", response_model=UserImage, tags=["user-images"])
|
@router.delete("/{image_id}", tags=["user-images"])
|
||||||
async def delete_image(
|
async def delete_image(
|
||||||
image_id: int,
|
image_id: int,
|
||||||
current_user: UserModel = Depends(get_current_user),
|
current_user: UserModel = Depends(get_current_user),
|
||||||
@ -103,12 +108,12 @@ async def delete_image(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
# 先检查图片是否存在
|
# 检查图片是否存在且属于当前用户
|
||||||
db_image = await user_image_service.get_user_image(db, image_id=image_id)
|
db_image = await user_image_service.get_user_image(db, image_id=image_id)
|
||||||
if db_image is None:
|
if db_image is None:
|
||||||
raise HTTPException(status_code=404, detail="图片不存在")
|
raise BusinessError("图片不存在", code=404)
|
||||||
if db_image.user_id != current_user.id:
|
if db_image.user_id != current_user.id:
|
||||||
raise HTTPException(status_code=403, detail="没有权限删除此图片")
|
raise BusinessError("没有权限删除此图片", code=403)
|
||||||
|
|
||||||
# 执行删除
|
deleted_image = await user_image_service.delete_user_image(db=db, image_id=image_id)
|
||||||
return await user_image_service.delete_user_image(db=db, image_id=image_id)
|
return StandardResponse(code=200, data=deleted_image)
|
||||||
@ -8,10 +8,15 @@ from app.db.database import get_db
|
|||||||
from app.api.deps import get_current_user
|
from app.api.deps import get_current_user
|
||||||
from app.models.users import User as UserModel
|
from app.models.users import User as UserModel
|
||||||
from app.core.exceptions import BusinessError
|
from app.core.exceptions import BusinessError
|
||||||
|
from app.schemas.response import StandardResponse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 创建日志记录器
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get("/me", response_model=User, tags=["users"])
|
@router.get("/me", tags=["users"])
|
||||||
async def read_user_me(
|
async def read_user_me(
|
||||||
current_user: UserModel = Depends(get_current_user)
|
current_user: UserModel = Depends(get_current_user)
|
||||||
):
|
):
|
||||||
@ -20,9 +25,9 @@ async def read_user_me(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
return current_user
|
return StandardResponse(code=200, data=current_user)
|
||||||
|
|
||||||
@router.put("/me", response_model=User, tags=["users"])
|
@router.put("/me", tags=["users"])
|
||||||
async def update_user_me(
|
async def update_user_me(
|
||||||
user_update: UserUpdate,
|
user_update: UserUpdate,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@ -33,12 +38,12 @@ async def update_user_me(
|
|||||||
|
|
||||||
需要JWT令牌认证
|
需要JWT令牌认证
|
||||||
"""
|
"""
|
||||||
user = await user_service.update_user(db, user_id=current_user.id, user_update=user_update)
|
result = await user_service.update_user(db, user_id=current_user.id, user_update=user_update)
|
||||||
if user is None:
|
if result is None:
|
||||||
raise BusinessError("用户更新失败", code=500)
|
raise BusinessError("用户更新失败", code=500)
|
||||||
return user
|
return StandardResponse(code=200, data=result)
|
||||||
|
|
||||||
@router.get("/{user_id}", response_model=User, tags=["users"])
|
@router.get("/{user_id}", tags=["users"])
|
||||||
async def read_user(
|
async def read_user(
|
||||||
user_id: int,
|
user_id: int,
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
@ -47,4 +52,4 @@ async def read_user(
|
|||||||
db_user = await user_service.get_user(db, user_id=user_id)
|
db_user = await user_service.get_user(db, user_id=user_id)
|
||||||
if db_user is None:
|
if db_user is None:
|
||||||
raise BusinessError("用户不存在", code=404)
|
raise BusinessError("用户不存在", code=404)
|
||||||
return db_user
|
return StandardResponse(code=200, data=db_user)
|
||||||
@ -1,8 +1,13 @@
|
|||||||
from fastapi import HTTPException, Request
|
from fastapi import HTTPException, Request
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.exceptions import RequestValidationError
|
from fastapi.exceptions import RequestValidationError
|
||||||
|
import logging
|
||||||
from app.schemas.response import ErrorResponse
|
from app.schemas.response import ErrorResponse
|
||||||
|
|
||||||
|
# 创建日志记录器
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
class BusinessError(Exception):
|
class BusinessError(Exception):
|
||||||
"""业务错误异常,使用标准响应格式"""
|
"""业务错误异常,使用标准响应格式"""
|
||||||
def __init__(self, message: str, code: int = 500):
|
def __init__(self, message: str, code: int = 500):
|
||||||
@ -13,12 +18,16 @@ class BusinessError(Exception):
|
|||||||
# 业务异常处理器
|
# 业务异常处理器
|
||||||
async def business_exception_handler(request: Request, exc: BusinessError):
|
async def business_exception_handler(request: Request, exc: BusinessError):
|
||||||
"""将业务异常转换为标准响应格式"""
|
"""将业务异常转换为标准响应格式"""
|
||||||
|
logger.debug(f"处理业务异常: code={exc.code}, message={exc.message}")
|
||||||
|
|
||||||
|
error_response = ErrorResponse(
|
||||||
|
code=exc.code,
|
||||||
|
message=exc.message
|
||||||
|
)
|
||||||
|
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=200, # 返回200状态码,但在响应内容中设置业务错误码
|
status_code=200, # 始终返回200状态码,业务错误码在响应内容中
|
||||||
content=ErrorResponse(
|
content=error_response.model_dump()
|
||||||
code=exc.code,
|
|
||||||
message=exc.message
|
|
||||||
).model_dump()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 请求验证错误处理器
|
# 请求验证错误处理器
|
||||||
@ -31,16 +40,35 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE
|
|||||||
error_messages.append(f"{loc_str}: {error.get('msg')}")
|
error_messages.append(f"{loc_str}: {error.get('msg')}")
|
||||||
|
|
||||||
error_message = ", ".join(error_messages)
|
error_message = ", ".join(error_messages)
|
||||||
|
logger.debug(f"处理请求验证错误: {error_message}")
|
||||||
|
|
||||||
|
error_response = ErrorResponse(
|
||||||
|
code=422,
|
||||||
|
message=f"请求参数验证错误: {error_message}"
|
||||||
|
)
|
||||||
|
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=422, # 保持422状态码,表示验证错误
|
status_code=200, # 与业务异常一致,返回200状态码
|
||||||
content=ErrorResponse(
|
content=error_response.model_dump()
|
||||||
code=422,
|
)
|
||||||
message=f"请求参数验证错误: {error_message}"
|
|
||||||
).model_dump()
|
# HTTP异常处理器
|
||||||
|
async def http_exception_handler(request: Request, exc: HTTPException):
|
||||||
|
"""将HTTP异常转换为标准错误响应"""
|
||||||
|
logger.debug(f"处理HTTP异常: status_code={exc.status_code}, detail={exc.detail}")
|
||||||
|
|
||||||
|
error_response = ErrorResponse(
|
||||||
|
code=exc.status_code,
|
||||||
|
message=str(exc.detail)
|
||||||
|
)
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
status_code=200, # 与业务异常一致,返回200状态码
|
||||||
|
content=error_response.model_dump()
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_exception_handlers(app):
|
def add_exception_handlers(app):
|
||||||
"""添加异常处理器到FastAPI应用"""
|
"""添加异常处理器到FastAPI应用"""
|
||||||
app.add_exception_handler(BusinessError, business_exception_handler)
|
app.add_exception_handler(BusinessError, business_exception_handler)
|
||||||
app.add_exception_handler(RequestValidationError, validation_exception_handler)
|
app.add_exception_handler(RequestValidationError, validation_exception_handler)
|
||||||
|
app.add_exception_handler(HTTPException, http_exception_handler)
|
||||||
@ -2,10 +2,26 @@ from typing import Any, Callable, Dict, Optional
|
|||||||
from fastapi import FastAPI, Request, Response
|
from fastapi import FastAPI, Request, Response
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
from starlette.middleware.base import BaseHTTPMiddleware
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
from starlette.types import ASGIApp
|
from starlette.types import ASGIApp
|
||||||
from app.schemas.response import StandardResponse, ErrorResponse
|
from app.schemas.response import StandardResponse, ErrorResponse
|
||||||
|
|
||||||
|
# 创建日志记录器并确保它正确配置
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
# 添加控制台处理器确保日志显示
|
||||||
|
if not logger.handlers:
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setLevel(logging.DEBUG)
|
||||||
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
logger.propagate = False # 避免重复日志
|
||||||
|
|
||||||
|
|
||||||
class ResponseMiddleware(BaseHTTPMiddleware):
|
class ResponseMiddleware(BaseHTTPMiddleware):
|
||||||
"""
|
"""
|
||||||
中间件:统一处理API响应格式
|
中间件:统一处理API响应格式
|
||||||
@ -14,48 +30,80 @@ class ResponseMiddleware(BaseHTTPMiddleware):
|
|||||||
业务错误:{code:500, message:""}
|
业务错误:{code:500, message:""}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, app: ASGIApp):
|
||||||
|
logger.warning("======== 初始化响应中间件 ========")
|
||||||
|
super().__init__(app)
|
||||||
|
|
||||||
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
||||||
|
logger.warning(f"===== 中间件处理请求: {request.method} {request.url.path} =====")
|
||||||
|
|
||||||
# 不需要处理的路径
|
# 不需要处理的路径
|
||||||
exclude_paths = ["/docs", "/redoc", "/openapi.json"]
|
exclude_paths = ["/docs", "/redoc", "/openapi.json"]
|
||||||
if any(request.url.path.startswith(path) for path in exclude_paths):
|
if any(request.url.path.startswith(path) for path in exclude_paths):
|
||||||
|
logger.warning(f"跳过处理: {request.url.path}")
|
||||||
return await call_next(request)
|
return await call_next(request)
|
||||||
|
|
||||||
# 获取原始响应
|
# 获取原始响应
|
||||||
response = await call_next(request)
|
|
||||||
|
|
||||||
# 如果不是200系列响应或不是JSON响应,直接返回
|
|
||||||
if response.status_code >= 300 or response.headers.get("content-type") != "application/json":
|
|
||||||
return response
|
|
||||||
|
|
||||||
# 读取响应内容
|
|
||||||
try:
|
try:
|
||||||
# 使用JSONResponse的_render方法获取内容
|
response = await call_next(request)
|
||||||
if isinstance(response, JSONResponse):
|
logger.warning(f"请求处理完成: {request.url.path}, 状态码: {response.status_code}")
|
||||||
# 获取原始数据
|
|
||||||
raw_data = response.body.decode("utf-8")
|
# 检查内容类型
|
||||||
data = json.loads(raw_data)
|
content_type = response.headers.get("content-type", "")
|
||||||
|
logger.warning(f"响应内容类型: {content_type}")
|
||||||
# 已经是标准格式,不再封装
|
|
||||||
if isinstance(data, dict) and "code" in data and ("data" in data or "message" in data):
|
# 如果不是JSON响应,直接返回
|
||||||
return response
|
if "application/json" not in content_type:
|
||||||
|
logger.warning(f"非JSON响应,跳过处理: {content_type}")
|
||||||
# 创建新的标准响应
|
|
||||||
std_response = StandardResponse(code=200, data=data)
|
|
||||||
|
|
||||||
# 创建新的JSONResponse
|
|
||||||
return JSONResponse(
|
|
||||||
content=std_response.model_dump(),
|
|
||||||
status_code=response.status_code,
|
|
||||||
headers=dict(response.headers)
|
|
||||||
)
|
|
||||||
# 处理流式响应或其他类型响应
|
|
||||||
else:
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
# 读取响应内容
|
||||||
|
try:
|
||||||
|
# 使用JSONResponse的方法获取内容
|
||||||
|
if isinstance(response, JSONResponse):
|
||||||
|
# 获取原始数据
|
||||||
|
raw_data = response.body.decode("utf-8")
|
||||||
|
data = json.loads(raw_data)
|
||||||
|
|
||||||
|
logger.warning(f"原始响应数据: {data}")
|
||||||
|
|
||||||
|
# 已经是标准格式,不再封装
|
||||||
|
if isinstance(data, dict) and "code" in data and ("data" in data or "message" in data):
|
||||||
|
logger.warning("响应已经是标准格式,不再包装")
|
||||||
|
return response
|
||||||
|
|
||||||
|
# 创建新的标准响应
|
||||||
|
std_response = StandardResponse(code=200, data=data)
|
||||||
|
logger.warning(f"包装为标准响应: code=200, data类型={type(data).__name__}")
|
||||||
|
|
||||||
|
# 创建新的JSONResponse
|
||||||
|
wrapped_response = JSONResponse(
|
||||||
|
content=std_response.model_dump(),
|
||||||
|
status_code=200, # 始终返回200状态码,错误码在响应内容中
|
||||||
|
headers=dict(response.headers)
|
||||||
|
)
|
||||||
|
logger.warning("返回包装后的响应")
|
||||||
|
return wrapped_response
|
||||||
|
# 处理流式响应或其他类型响应
|
||||||
|
else:
|
||||||
|
logger.warning(f"非JSONResponse类型响应: {type(response)}")
|
||||||
|
return response
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 出现异常,记录日志
|
||||||
|
logger.error(f"处理响应内容时发生异常: {str(e)}", exc_info=True)
|
||||||
|
# 返回原始响应
|
||||||
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 出现异常,返回原始响应
|
logger.error(f"中间件处理请求时发生异常: {str(e)}", exc_info=True)
|
||||||
return response
|
raise
|
||||||
|
|
||||||
|
# 使用函数工厂模式创建中间件,确保每次创建新实例
|
||||||
|
def create_response_middleware():
|
||||||
|
return ResponseMiddleware
|
||||||
|
|
||||||
def add_response_middleware(app: FastAPI) -> None:
|
def add_response_middleware(app: FastAPI) -> None:
|
||||||
"""添加响应处理中间件到FastAPI应用"""
|
"""添加响应处理中间件到FastAPI应用"""
|
||||||
app.add_middleware(ResponseMiddleware)
|
logger.warning("添加响应处理中间件到FastAPI应用")
|
||||||
|
# 使用函数工厂以确保每次获取新的中间件实例
|
||||||
|
app.add_middleware(create_response_middleware())
|
||||||
22
app/main.py
22
app/main.py
@ -4,12 +4,13 @@ from contextlib import asynccontextmanager
|
|||||||
import logging
|
import logging
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.api.v1.api import api_router
|
from app.api.v1.api import api_router
|
||||||
from app.core.middleware import add_response_middleware
|
|
||||||
from app.core.exceptions import add_exception_handlers
|
from app.core.exceptions import add_exception_handlers
|
||||||
|
from app.core.middleware import add_response_middleware
|
||||||
|
from app.schemas.response import StandardResponse
|
||||||
|
|
||||||
# 配置日志
|
# 配置日志
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.DEBUG, # 设置为DEBUG级别以显示更多日志
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
)
|
)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -32,6 +33,8 @@ app = FastAPI(
|
|||||||
lifespan=lifespan
|
lifespan=lifespan
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger.info("开始配置应用中间件和路由...")
|
||||||
|
|
||||||
# 配置CORS
|
# 配置CORS
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
@ -40,20 +43,25 @@ app.add_middleware(
|
|||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
logger.info("CORS中间件已添加")
|
||||||
# 添加响应中间件
|
|
||||||
add_response_middleware(app)
|
|
||||||
|
|
||||||
# 添加异常处理器
|
# 添加异常处理器
|
||||||
add_exception_handlers(app)
|
add_exception_handlers(app)
|
||||||
|
logger.info("异常处理器已添加")
|
||||||
|
|
||||||
|
# add_response_middleware(app)
|
||||||
|
# logger.info("响应中间件已添加")
|
||||||
|
|
||||||
# 包含API路由
|
# 包含API路由
|
||||||
app.include_router(api_router, prefix=settings.API_V1_STR)
|
app.include_router(api_router, prefix=settings.API_V1_STR)
|
||||||
|
logger.info(f"API路由已添加,前缀: {settings.API_V1_STR}")
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
async def root():
|
async def root():
|
||||||
return {"message": "欢迎使用美搭Meida API服务"}
|
logger.info("访问根路径")
|
||||||
|
return StandardResponse(code=200, data={"message": "欢迎使用美搭Meida API服务"})
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def health_check():
|
async def health_check():
|
||||||
return {"status": "healthy"}
|
logger.debug("健康检查")
|
||||||
|
return StandardResponse(code=200, data={"status": "healthy"})
|
||||||
@ -6,11 +6,12 @@ T = TypeVar('T')
|
|||||||
|
|
||||||
class StandardResponse(BaseModel, Generic[T]):
|
class StandardResponse(BaseModel, Generic[T]):
|
||||||
"""标准API响应格式"""
|
"""标准API响应格式"""
|
||||||
code: int = 200
|
code: int = Field(200, description="状态码,200表示成功,其他值表示错误")
|
||||||
message: Optional[str] = None
|
message: Optional[str] = Field(None, description="消息,通常在错误时提供")
|
||||||
data: Optional[T] = None
|
data: Optional[T] = Field(None, description="响应数据")
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"code": 200,
|
"code": 200,
|
||||||
@ -21,11 +22,12 @@ class StandardResponse(BaseModel, Generic[T]):
|
|||||||
|
|
||||||
class ErrorResponse(BaseModel):
|
class ErrorResponse(BaseModel):
|
||||||
"""错误响应格式"""
|
"""错误响应格式"""
|
||||||
code: int = 500
|
code: int = Field(500, description="错误码,非200值")
|
||||||
message: str
|
message: str = Field(..., description="错误消息")
|
||||||
data: None = None
|
data: None = Field(None, description="数据字段,错误时为null")
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
json_schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"code": 500,
|
"code": 500,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from app.schemas.user import User
|
||||||
|
|
||||||
class UserImageBase(BaseModel):
|
class UserImageBase(BaseModel):
|
||||||
"""用户形象基础模式"""
|
"""用户形象基础模式"""
|
||||||
@ -9,7 +10,7 @@ class UserImageBase(BaseModel):
|
|||||||
|
|
||||||
class UserImageCreate(UserImageBase):
|
class UserImageCreate(UserImageBase):
|
||||||
"""创建用户形象请求"""
|
"""创建用户形象请求"""
|
||||||
pass
|
user_id: Optional[int] = Field(None, description="用户ID,可选,通常由系统设置")
|
||||||
|
|
||||||
class UserImageInDB(UserImageBase):
|
class UserImageInDB(UserImageBase):
|
||||||
"""数据库中的用户形象数据"""
|
"""数据库中的用户形象数据"""
|
||||||
@ -27,4 +28,11 @@ class UserImage(UserImageInDB):
|
|||||||
class UserImageUpdate(BaseModel):
|
class UserImageUpdate(BaseModel):
|
||||||
"""更新用户形象请求"""
|
"""更新用户形象请求"""
|
||||||
image_url: Optional[str] = Field(None, description="图片URL")
|
image_url: Optional[str] = Field(None, description="图片URL")
|
||||||
is_default: Optional[bool] = Field(None, description="是否为默认形象")
|
is_default: Optional[bool] = Field(None, description="是否为默认形象")
|
||||||
|
|
||||||
|
class UserImageWithUser(UserImage):
|
||||||
|
"""包含用户信息的用户形象响应"""
|
||||||
|
user: Optional[User] = Field(None, description="用户信息")
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
@ -10,7 +10,7 @@ async def get_user_image(db: AsyncSession, image_id: int):
|
|||||||
result = await db.execute(select(UserImage).filter(UserImage.id == image_id))
|
result = await db.execute(select(UserImage).filter(UserImage.id == image_id))
|
||||||
return result.scalars().first()
|
return result.scalars().first()
|
||||||
|
|
||||||
async def get_user_images(db: AsyncSession, user_id: int, skip: int = 0, limit: int = 100):
|
async def get_user_images_by_user(db: AsyncSession, user_id: int, skip: int = 0, limit: int = 100):
|
||||||
"""获取用户的所有形象图片"""
|
"""获取用户的所有形象图片"""
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(UserImage)
|
select(UserImage)
|
||||||
@ -21,14 +21,17 @@ async def get_user_images(db: AsyncSession, user_id: int, skip: int = 0, limit:
|
|||||||
)
|
)
|
||||||
return result.scalars().all()
|
return result.scalars().all()
|
||||||
|
|
||||||
async def create_user_image(db: AsyncSession, user_id: int, image: UserImageCreate):
|
async def create_user_image(db: AsyncSession, image: UserImageCreate):
|
||||||
"""创建用户形象"""
|
"""创建用户形象
|
||||||
|
|
||||||
|
image: 包含user_id的UserImageCreate对象
|
||||||
|
"""
|
||||||
# 如果设置为默认形象,先重置用户的所有形象为非默认
|
# 如果设置为默认形象,先重置用户的所有形象为非默认
|
||||||
if image.is_default:
|
if image.is_default and image.user_id:
|
||||||
await reset_default_images(db, user_id)
|
await reset_default_images(db, image.user_id)
|
||||||
|
|
||||||
db_image = UserImage(
|
db_image = UserImage(
|
||||||
user_id=user_id,
|
user_id=image.user_id,
|
||||||
image_url=image.image_url,
|
image_url=image.image_url,
|
||||||
is_default=image.is_default
|
is_default=image.is_default
|
||||||
)
|
)
|
||||||
@ -37,23 +40,23 @@ async def create_user_image(db: AsyncSession, user_id: int, image: UserImageCrea
|
|||||||
await db.refresh(db_image)
|
await db.refresh(db_image)
|
||||||
return db_image
|
return db_image
|
||||||
|
|
||||||
async def update_user_image(db: AsyncSession, image_id: int, image_update: UserImageUpdate):
|
async def update_user_image(db: AsyncSession, image_id: int, image: UserImageUpdate):
|
||||||
"""更新用户形象"""
|
"""更新用户形象"""
|
||||||
db_image = await get_user_image(db, image_id)
|
db_image = await get_user_image(db, image_id)
|
||||||
if not db_image:
|
if not db_image:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 处理默认形象逻辑
|
# 处理默认形象逻辑
|
||||||
if image_update.is_default is not None and image_update.is_default and not db_image.is_default:
|
if image.is_default is not None and image.is_default and not db_image.is_default:
|
||||||
# 如果设置为默认且之前不是默认,重置其他形象
|
# 如果设置为默认且之前不是默认,重置其他形象
|
||||||
await reset_default_images(db, db_image.user_id)
|
await reset_default_images(db, db_image.user_id)
|
||||||
db_image.is_default = True
|
db_image.is_default = True
|
||||||
elif image_update.is_default is not None:
|
elif image.is_default is not None:
|
||||||
db_image.is_default = image_update.is_default
|
db_image.is_default = image.is_default
|
||||||
|
|
||||||
# 更新图片URL
|
# 更新图片URL
|
||||||
if image_update.image_url:
|
if image.image_url:
|
||||||
db_image.image_url = image_update.image_url
|
db_image.image_url = image.image_url
|
||||||
|
|
||||||
await db.commit()
|
await db.commit()
|
||||||
await db.refresh(db_image)
|
await db.refresh(db_image)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user