重构表结构:合并 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:
2026-07-28 23:48:57 +08:00
parent 118c5cbe96
commit e75833ee4b
14 changed files with 519 additions and 285 deletions
+4 -4
View File
@@ -71,7 +71,7 @@ def test_create_user(client: TestClient) -> None:
assert r.status_code == 201
body = r.json()
assert body["user"]["email_verified"] is True
assert body["profile"]["role"] == "user"
assert body["user"]["role"] == "user"
def test_create_user_with_role(client: TestClient) -> None:
@@ -87,7 +87,7 @@ def test_create_user_with_role(client: TestClient) -> None:
},
)
assert r.status_code == 201
assert r.json()["profile"]["role"] == "admin"
assert r.json()["user"]["role"] == "admin"
def test_create_user_duplicate_email(client: TestClient) -> None:
@@ -141,7 +141,7 @@ def test_update_user_role(client: TestClient, monkeypatch) -> None:
json={"role": "admin"},
)
assert r.status_code == 200
assert r.json()["profile"]["role"] == "admin"
assert r.json()["user"]["role"] == "admin"
def test_update_user_disable(client: TestClient, monkeypatch) -> None:
@@ -157,7 +157,7 @@ def test_update_user_disable(client: TestClient, monkeypatch) -> None:
json={"is_disabled": True},
)
assert r.status_code == 200
assert r.json()["profile"]["is_disabled"] is True
assert r.json()["user"]["is_disabled"] is True
client.patch(
f"/api/v1/admin/users/{info['user_id']}",
+1 -1
View File
@@ -264,7 +264,7 @@ def test_me(client: TestClient, monkeypatch) -> None:
assert r.status_code == 200
body = r.json()
assert body["user"]["email"] == email
assert body["profile"]["username"] == "我的信息"
assert body["user"]["username"] == "我的信息"
def test_me_unauthenticated(client: TestClient) -> None: