重构表结构:合并 profiles→users,展平 API 响应,新增计数器字段
- models: 删除 Profile 模型,字段合并到 User;User 新增云朵/公开/收藏计数器;Cloud 新增 favorite_count - schemas/serializers: 展平 UserOut/AuthOut/MeOut/AdminUserOut,移除嵌套 profile - deps: user.profile.role→user.role,移除 selectinload profile - auth/register: 注册时直接设置 user 字段,不再创建 Profile - clouds: 创建/删除云朵时同步 user.cloud_count 计数器,状态变化时同步 public_cloud_count - favorites: 点赞/取消时同步 cloud.favorite_count 计数器 - admin: 审批/隐藏/批量删时同步 public_cloud_count 计数器 - profiles/stats: 用计数器替代实时 COUNT 查询 - alembic: 新增 migration 合并 profiles 到 users,初始化 counters
This commit is contained in:
+20
-27
@@ -1,12 +1,10 @@
|
||||
from app.config import settings
|
||||
from app.models import Cloud, CloudType, Profile, User
|
||||
from app.models import Cloud, CloudType, User
|
||||
from app.schemas import (
|
||||
CloudOut,
|
||||
CloudOwnerOut,
|
||||
CloudTypeOut,
|
||||
CloudTypeSummary,
|
||||
ProfileOut,
|
||||
PublicProfileOut,
|
||||
UserOut,
|
||||
)
|
||||
|
||||
@@ -17,31 +15,18 @@ def media_url(path: str | None) -> str | None:
|
||||
return f"{settings.media_base_url}/{path.lstrip('/')}"
|
||||
|
||||
|
||||
def profile_out(profile: Profile) -> ProfileOut:
|
||||
return ProfileOut(
|
||||
id=profile.id,
|
||||
username=profile.username,
|
||||
avatar_url=media_url(profile.avatar_path),
|
||||
role=profile.role,
|
||||
is_disabled=profile.is_disabled,
|
||||
created_at=profile.created_at,
|
||||
)
|
||||
|
||||
|
||||
def public_profile_out(profile: Profile) -> PublicProfileOut:
|
||||
return PublicProfileOut(
|
||||
id=profile.id,
|
||||
username=profile.username,
|
||||
avatar_url=media_url(profile.avatar_path),
|
||||
created_at=profile.created_at,
|
||||
)
|
||||
|
||||
|
||||
def user_out(user: User) -> UserOut:
|
||||
return UserOut(
|
||||
id=user.id,
|
||||
email=user.email,
|
||||
email_verified=user.email_verified_at is not None,
|
||||
username=user.username,
|
||||
avatar_url=media_url(user.avatar_path),
|
||||
role=user.role,
|
||||
is_disabled=user.is_disabled,
|
||||
cloud_count=user.cloud_count,
|
||||
public_cloud_count=user.public_cloud_count,
|
||||
collection_count=user.collection_count,
|
||||
created_at=user.created_at,
|
||||
)
|
||||
|
||||
@@ -68,9 +53,15 @@ def cloud_type_out(cloud_type: CloudType) -> CloudTypeOut:
|
||||
)
|
||||
|
||||
|
||||
def cloud_out(cloud: Cloud, *, include_private: bool = True) -> CloudOut:
|
||||
def cloud_out(
|
||||
cloud: Cloud,
|
||||
*,
|
||||
include_private: bool = True,
|
||||
favorite_count: int | None = None,
|
||||
is_favorited: bool = False,
|
||||
) -> CloudOut:
|
||||
cloud_type = cloud.cloud_type
|
||||
profile = cloud.user.profile
|
||||
owner = cloud.user
|
||||
type_name = cloud_type.name if cloud_type else (cloud.custom_cloud_type or "未知")
|
||||
rarity = cloud_type.rarity if cloud_type else "common"
|
||||
return CloudOut(
|
||||
@@ -90,8 +81,10 @@ def cloud_out(cloud: Cloud, *, include_private: bool = True) -> CloudOut:
|
||||
created_at=cloud.created_at,
|
||||
updated_at=cloud.updated_at,
|
||||
cloud_type=cloud_type_summary(cloud_type) if cloud_type else None,
|
||||
owner=CloudOwnerOut(id=profile.id, username=profile.username),
|
||||
owner=CloudOwnerOut(id=owner.id, username=owner.username),
|
||||
cloud_type_name=type_name,
|
||||
cloud_type_rarity=rarity,
|
||||
username=profile.username,
|
||||
username=owner.username,
|
||||
favorite_count=favorite_count if favorite_count is not None else 0,
|
||||
is_favorited=is_favorited,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user