Files
X25020501_card_book/core/routers/user/routes.py

196 lines
6.1 KiB
Python

# -*- coding = utf-8 -*-
# @Time : 2025/2/13 下午4:53
# @File : routes.py
# @Software : PyCharm
# @Author : xingc
# @Desc :
from typing import List, Literal
from fastapi import APIRouter, Query, Depends, HTTPException, status
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from core.base import schema as base_schema
from core.db.crud import CRUD
from core.db.engine import get_async_session
from core.db.models import User, UserFollows, UserCollection
from core.routers.auth.schema import LoginUser
from core.routers.auth.services import get_current_user_form_http
from . import schema
user_router = APIRouter(prefix='/user', tags=['用户模块'])
@user_router.get('/me/info', summary='用户信息(我的)', response_model=base_schema.BaseResponse[schema.User])
async def get_me_info(
login_user: LoginUser = Depends(get_current_user_form_http),
db_session: AsyncSession = Depends(get_async_session)
):
db_crud = CRUD(db_session, User)
user = await db_crud.get(filters={'user_id': login_user.user_id})
if user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='用户不存在')
user.displayed_card_total = await db_crud.total(
model=UserCollection,
filters={
'user_id': login_user.user_id,
'displayed': True}
)
return {'data': user}
@user_router.get(
'/visit/{user_id}/info',
summary='用户信息(访问者)',
response_model=base_schema.BaseResponse[schema.VisitUser]
)
async def get_visit_user_info(
user_id: int,
login_user: LoginUser = Depends(get_current_user_form_http),
db_session: AsyncSession = Depends(get_async_session)
):
if user_id == login_user.user_id:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='无法操作')
db_crud = CRUD(db_session, User)
user = await db_crud.get(filters={'user_id': user_id})
if user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='访问用户不存在')
user.is_follow = await db_crud.exists(
model=UserFollows,
filters={
'follower_id': login_user.user_id,
'followed_id': user_id
}
)
user.displayed_card_total = await db_crud.total(
model=UserCollection,
filters={
'user_id': user.user_id,
'displayed': True}
)
return {'data': user}
@user_router.get(
'/followers/all',
summary='获取所有关注列表',
response_model=base_schema.BaseResponse[
base_schema.Paginated[
List[schema.LiteUser]
]
]
)
async def get_all_followers(
login_user: LoginUser = Depends(get_current_user_form_http),
page: int = Query(default=1, gt=0),
page_size: int = Query(default=15, gt=0, le=200),
db_session: AsyncSession = Depends(get_async_session)
):
# 组装查询条件
conditions = [
UserFollows.follower_id == login_user.user_id
]
# 记录总数查询
total_stmt = (
select(func.count()).select_from(UserFollows).filter(*conditions)
)
total = await db_session.execute(total_stmt)
# 分页记录查询
stmt = (
select(User, UserFollows)
.join(User, UserFollows.followed_id == User.user_id)
.where(*conditions)
.order_by(UserFollows.created_at.desc()).limit(page_size).offset((page - 1) * page_size)
)
records = await db_session.execute(stmt)
return {
'data': {
'list': records.scalars().all(),
'total': total.scalar(),
'page': page,
'page_size': page_size,
},
}
@user_router.post('/me/update', summary='更新用户信息', response_model=base_schema.BaseResponse[schema.User])
async def update_me(
payload: schema.UpdateUserIn,
login_user: LoginUser = Depends(get_current_user_form_http),
db_session: AsyncSession = Depends(get_async_session)
):
db_crud = CRUD(db_session, User)
result = await db_crud.update(payload.model_dump(exclude_none=True), filters={'user_id': login_user.user_id})
if result is None:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='无法操作')
return {'data': result}
@user_router.post('/follow/{user_id}/', summary='新增/取消关注用户', response_model=base_schema.BaseResponse)
async def follow_user(
user_id: int,
action: Literal['follower', 'unfollower'],
login_user: LoginUser = Depends(get_current_user_form_http),
db_session: AsyncSession = Depends(get_async_session)
):
if user_id == login_user.user_id:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='无法操作')
db_crud = CRUD(db_session, User)
follower_user: User | None = await db_crud.get(filters={'user_id': user_id})
if follower_user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='被关注者不存在')
db_crud = CRUD(db_session, UserFollows)
record = {
'follower_id': login_user.user_id,
'followed_id': follower_user.user_id,
}
if action == 'follower':
await db_crud.create(data=record, filters=record)
if action == 'unfollower':
await db_crud.delete(filters=record)
return {'message': 'ok'}
@user_router.post(
'/search/',
summary='搜索用户',
response_model=base_schema.BaseResponse[
base_schema.Paginated[
List[schema.LiteUser]
]
]
)
async def search_user(
nickname: str = Query(...),
page_size: int = Query(default=30, gt=0, le=30),
login_user: LoginUser = Depends(get_current_user_form_http),
db_session: AsyncSession = Depends(get_async_session)
):
db_crud = CRUD(db_session, User)
users, total = await db_crud.get_paginated(
page_size=page_size,
filters={
'nickname__like': nickname,
'user_id__ne': login_user.user_id
}
)
return {'data': {
'list': users,
'total': total,
'page_size': page_size
}}