Files
market_page/backend/community/views.py
jeremygan2021 b4ac97c3c2 new
2026-02-12 14:23:36 +08:00

125 lines
4.8 KiB
Python

from rest_framework import viewsets, status, mixins, parsers, filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import serializers
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from drf_spectacular.utils import extend_schema
from shop.models import WeChatUser
from .models import Activity, ActivitySignup, Topic, Reply, TopicMedia
from .serializers import ActivitySerializer, ActivitySignupSerializer, TopicSerializer, ReplySerializer, TopicMediaSerializer
def get_current_wechat_user(request):
"""
根据 Authorization 头获取当前微信用户 (复用 shop app 的逻辑)
"""
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return None
token = auth_header.split(' ')[1]
signer = TimestampSigner()
try:
# 签名包含 openid
openid = signer.unsign(token, max_age=86400 * 30) # 30天有效
return WeChatUser.objects.filter(openid=openid).first()
except (BadSignature, SignatureExpired):
return None
class ActivityViewSet(viewsets.ReadOnlyModelViewSet):
"""
社区活动接口
"""
queryset = Activity.objects.filter(is_active=True).order_by('-created_at')
serializer_class = ActivitySerializer
@extend_schema(summary="报名活动")
@action(detail=True, methods=['post'])
def signup(self, request, pk=None):
user = get_current_wechat_user(request)
if not user:
return Response({'error': '请先登录'}, status=401)
activity = self.get_object()
# Check if already signed up
if ActivitySignup.objects.filter(activity=activity, user=user).exists():
return Response({'error': '您已报名该活动'}, status=400)
if activity.signups.count() >= activity.max_participants:
return Response({'error': '活动名额已满'}, status=400)
signup = ActivitySignup.objects.create(activity=activity, user=user)
serializer = ActivitySignupSerializer(signup)
return Response(serializer.data, status=201)
@extend_schema(summary="我的报名记录")
@action(detail=False, methods=['get'])
def my_signups(self, request):
user = get_current_wechat_user(request)
if not user:
return Response({'error': '请先登录'}, status=401)
signups = ActivitySignup.objects.filter(user=user).order_by('-signup_time')
serializer = ActivitySignupSerializer(signups, many=True)
return Response(serializer.data)
class TopicViewSet(viewsets.ModelViewSet):
"""
技术论坛帖子接口
"""
queryset = Topic.objects.all()
serializer_class = TopicSerializer
filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
search_fields = ['title', 'content']
filterset_fields = ['category', 'is_pinned']
ordering_fields = ['created_at', 'view_count']
ordering = ['-is_pinned', '-created_at']
def perform_create(self, serializer):
user = get_current_wechat_user(self.request)
# Auth check is done in create or permission, but here we need user for save
if user:
serializer.save(author=user)
def create(self, request, *args, **kwargs):
user = get_current_wechat_user(request)
if not user:
return Response({'error': '请先登录'}, status=401)
return super().create(request, *args, **kwargs)
class ReplyViewSet(viewsets.ModelViewSet):
"""
帖子回复接口
"""
queryset = Reply.objects.all()
serializer_class = ReplySerializer
def perform_create(self, serializer):
user = get_current_wechat_user(self.request)
if user:
serializer.save(author=user)
def create(self, request, *args, **kwargs):
user = get_current_wechat_user(request)
if not user:
return Response({'error': '请先登录'}, status=401)
return super().create(request, *args, **kwargs)
class TopicMediaViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin):
"""
论坛多媒体资源上传接口
"""
queryset = TopicMedia.objects.all()
serializer_class = TopicMediaSerializer
parser_classes = [parsers.MultiPartParser, parsers.FormParser]
@extend_schema(summary="上传媒体文件 (返回URL用于Markdown)")
def create(self, request, *args, **kwargs):
user = get_current_wechat_user(request)
if not user:
return Response({'error': '请先登录'}, status=401)
# 允许上传时不关联 Topic (发帖前上传),或后续关联
# 主要是返回 url
return super().create(request, *args, **kwargs)