doc:DocManager 新增 QueryDocuments/QuerySeries 返回查询集,视图 get_queryset 改为委托;invite:新增 InviteManager(QuerySet/GetByInviteID/Create);sve:新增 SveManager(QuerySet/GetByCandidates/Upsert 支持 CreateDefaults);community:新增 CommunityManager(板块/分类/帖子/回复/点赞共 20 处,ToggleLike 封装点赞切换与计数同步,聚合查询保留原 values_list+annotate)。 视图层不再直接操作 ORM,类级 queryset 属性保留(DRF 必需);QueryPosts 收 Filters 字典以保持原边界行为。
151 lines
5.0 KiB
Python
151 lines
5.0 KiB
Python
"""模块:Community 社区数据访问层
|
||
|
||
官网社区(discuss.gvsds.com)的板块/分类/帖子/回复/点赞数据访问收敛在此,
|
||
视图层不直接操作 ORM。所有方法遵循帕斯卡命名法。
|
||
"""
|
||
|
||
import uuid
|
||
|
||
from django.db.models import Count, F
|
||
|
||
from .models import (
|
||
CommunityBoard,
|
||
CommunityCategory,
|
||
CommunityLike,
|
||
CommunityPost,
|
||
CommunityReply,
|
||
)
|
||
|
||
|
||
class CommunityManager:
|
||
"""社区管理器"""
|
||
|
||
# ========== 板块 / 分类 ==========
|
||
|
||
@staticmethod
|
||
def ListActiveBoards():
|
||
"""启用板块列表"""
|
||
return list(CommunityBoard.objects.filter(BoardStatus=1))
|
||
|
||
@staticmethod
|
||
def CountPostsByBoards(BoardUUIDs):
|
||
"""各板块的已发布帖子数 {板块bytes: 帖子数}(BoardUUIDs 为空返回 {})"""
|
||
if not BoardUUIDs:
|
||
return {}
|
||
return {
|
||
BoardUUID: PostCount
|
||
for BoardUUID, PostCount in CommunityPost.objects.filter(
|
||
PostStatus=1, BoardUUID__in=BoardUUIDs,
|
||
).values_list('BoardUUID').annotate(c=Count('PostUUID'))
|
||
}
|
||
|
||
@staticmethod
|
||
def ListActiveCategories():
|
||
"""启用分类列表"""
|
||
return list(CommunityCategory.objects.filter(CategoryStatus=1))
|
||
|
||
@staticmethod
|
||
def GetBoard(BoardUUID):
|
||
"""按 UUID 取板块(不存在返回 None)"""
|
||
return CommunityBoard.objects.filter(BoardUUID=BoardUUID).first()
|
||
|
||
@staticmethod
|
||
def GetActiveBoard(BoardUUID):
|
||
"""按 UUID 取启用板块(不存在或已停用返回 None)"""
|
||
return CommunityBoard.objects.filter(BoardUUID=BoardUUID, BoardStatus=1).first()
|
||
|
||
@staticmethod
|
||
def GetCategory(CategoryUUID):
|
||
"""按 UUID 取分类(UUID 为空返回 None)"""
|
||
if not CategoryUUID:
|
||
return None
|
||
return CommunityCategory.objects.filter(CategoryUUID=CategoryUUID).first()
|
||
|
||
# ========== 帖子 ==========
|
||
|
||
@staticmethod
|
||
def QueryPosts(Filters=None):
|
||
"""已发布帖子查询集
|
||
|
||
Filters 为附加过滤条件(键为 ORM lookup、值为已转换好的 bytes/str),
|
||
由调用方按「参数存在才过滤」的语义构造;为空表示仅限已发布。
|
||
"""
|
||
return CommunityPost.objects.filter(PostStatus=1, **(Filters or {}))
|
||
|
||
@staticmethod
|
||
def GetPost(PostUUID, OnlyPublished=False):
|
||
"""按 UUID 取帖子(OnlyPublished=True 时排除已删除;不存在返回 None)"""
|
||
qs = CommunityPost.objects.filter(PostUUID=PostUUID)
|
||
if OnlyPublished:
|
||
qs = qs.filter(PostStatus=1)
|
||
return qs.first()
|
||
|
||
@staticmethod
|
||
def CreatePost(BoardUUID, Title, Content, AuthorUUID, AuthorName, CategoryUUID=None):
|
||
"""发帖"""
|
||
return CommunityPost.objects.create(
|
||
PostUUID=uuid.uuid4().bytes,
|
||
BoardUUID=BoardUUID,
|
||
CategoryUUID=CategoryUUID,
|
||
Title=Title,
|
||
Content=Content,
|
||
AuthorUUID=AuthorUUID,
|
||
AuthorName=AuthorName,
|
||
)
|
||
|
||
@staticmethod
|
||
def IncreaseViewCount(PostUUID):
|
||
"""浏览量 +1(DB 侧原子自增)"""
|
||
CommunityPost.objects.filter(PostUUID=PostUUID).update(ViewCount=F('ViewCount') + 1)
|
||
|
||
@staticmethod
|
||
def IncreaseReplyCount(PostUUID):
|
||
"""回复数 +1(DB 侧原子自增)"""
|
||
CommunityPost.objects.filter(PostUUID=PostUUID).update(ReplyCount=F('ReplyCount') + 1)
|
||
|
||
# ========== 回复 ==========
|
||
|
||
@staticmethod
|
||
def ListReplies(PostUUID):
|
||
"""帖子下未删除回复列表"""
|
||
return CommunityReply.objects.filter(PostUUID=PostUUID, ReplyStatus=1)
|
||
|
||
@staticmethod
|
||
def CreateReply(PostUUID, AuthorUUID, AuthorName, Content, ReplyToUUID=None):
|
||
"""新增回复"""
|
||
return CommunityReply.objects.create(
|
||
ReplyUUID=uuid.uuid4().bytes,
|
||
PostUUID=PostUUID,
|
||
AuthorUUID=AuthorUUID,
|
||
AuthorName=AuthorName,
|
||
Content=Content,
|
||
ReplyToUUID=ReplyToUUID,
|
||
)
|
||
|
||
# ========== 点赞 ==========
|
||
|
||
@staticmethod
|
||
def HasLiked(PostUUID, AuthorUUID):
|
||
"""判断用户是否已点赞该帖子"""
|
||
return CommunityLike.objects.filter(PostUUID=PostUUID, AuthorUUID=AuthorUUID).exists()
|
||
|
||
@staticmethod
|
||
def ToggleLike(PostUUID, AuthorUUID):
|
||
"""切换点赞状态并同步帖子点赞数
|
||
|
||
Returns:
|
||
True 表示本次为点赞,False 表示本次为取消点赞
|
||
"""
|
||
existing = CommunityLike.objects.filter(PostUUID=PostUUID, AuthorUUID=AuthorUUID).first()
|
||
if existing is not None:
|
||
existing.delete()
|
||
CommunityPost.objects.filter(PostUUID=PostUUID).update(LikeCount=F('LikeCount') - 1)
|
||
return False
|
||
CommunityLike.objects.create(
|
||
LikeUUID=uuid.uuid4().bytes,
|
||
PostUUID=PostUUID,
|
||
AuthorUUID=AuthorUUID,
|
||
)
|
||
CommunityPost.objects.filter(PostUUID=PostUUID).update(LikeCount=F('LikeCount') + 1)
|
||
return True
|