Files
market_page/backend/competition/views.py
jeremygan2021 880192c358 比赛
2026-03-10 14:05:37 +08:00

274 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from rest_framework import viewsets, permissions, status, filters, serializers
from rest_framework.decorators import action
from rest_framework.response import Response
from django.db.models import Q
from shop.utils import get_current_wechat_user
from .models import Competition, CompetitionEnrollment, Project, ProjectFile, Score, Comment, ScoreDimension
from .serializers import (
CompetitionSerializer, CompetitionEnrollmentSerializer,
ProjectSerializer, ProjectFileSerializer,
ScoreSerializer, CommentSerializer, ScoreDimensionSerializer
)
from rest_framework.pagination import PageNumberPagination
class StandardResultsSetPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class CompetitionViewSet(viewsets.ReadOnlyModelViewSet):
"""
比赛视图集
"""
queryset = Competition.objects.filter(is_active=True).order_by('-created_at')
serializer_class = CompetitionSerializer
permission_classes = [permissions.AllowAny]
pagination_class = StandardResultsSetPagination
filter_backends = [filters.SearchFilter]
search_fields = ['title', 'description']
def get_queryset(self):
"""
获取比赛查询集,支持根据查询参数进行动态过滤
"""
queryset = super().get_queryset()
# 状态过滤
status_param = self.request.query_params.get('status')
if status_param and status_param != 'all':
queryset = queryset.filter(status=status_param)
return queryset
@action(detail=True, methods=['post'], permission_classes=[permissions.AllowAny])
def enroll(self, request, pk=None):
"""
报名参加比赛
"""
competition = self.get_object()
user = get_current_wechat_user(request)
if not user:
return Response({"detail": "未登录"}, status=status.HTTP_401_UNAUTHORIZED)
role = request.data.get('role', 'contestant')
# 检查是否已报名
if CompetitionEnrollment.objects.filter(competition=competition, user=user).exists():
return Response({"detail": "您已报名该比赛"}, status=status.HTTP_400_BAD_REQUEST)
enrollment = CompetitionEnrollment.objects.create(
competition=competition,
user=user,
role=role,
status='pending' # 默认待审核
)
return Response(CompetitionEnrollmentSerializer(enrollment).data, status=status.HTTP_201_CREATED)
@action(detail=True, methods=['get'])
def my_enrollment(self, request, pk=None):
"""
获取我的报名信息
"""
competition = self.get_object()
user = get_current_wechat_user(request)
if not user:
return Response({"detail": "未登录"}, status=status.HTTP_401_UNAUTHORIZED)
try:
enrollment = CompetitionEnrollment.objects.get(competition=competition, user=user)
return Response(CompetitionEnrollmentSerializer(enrollment).data)
except CompetitionEnrollment.DoesNotExist:
return Response({"detail": "未报名"}, status=status.HTTP_404_NOT_FOUND)
@action(detail=False, methods=['get'])
def my_enrollments(self, request):
"""
获取我的所有报名信息
"""
user = get_current_wechat_user(request)
if not user:
return Response([])
enrollments = CompetitionEnrollment.objects.filter(user=user)
return Response(CompetitionEnrollmentSerializer(enrollments, many=True).data)
class ProjectViewSet(viewsets.ModelViewSet):
"""
参赛项目视图集
"""
serializer_class = ProjectSerializer
permission_classes = [permissions.AllowAny]
pagination_class = StandardResultsSetPagination
def get_queryset(self):
queryset = Project.objects.all()
competition_id = self.request.query_params.get('competition')
if competition_id:
queryset = queryset.filter(competition_id=competition_id)
contestant_id = self.request.query_params.get('contestant')
if contestant_id:
queryset = queryset.filter(contestant_id=contestant_id)
# 如果是普通用户,只能看到已提交的项目,或者自己草稿的项目
user = get_current_wechat_user(self.request)
if user:
# 查找用户在这个比赛中的角色
# 如果是评委,可以看到所有项目(包括草稿吗?通常评委只看提交的)
# 这里简化评委看所有submitted用户看所有submitted + 自己的draft
# 找到用户参与的所有比赛角色
enrollments = CompetitionEnrollment.objects.filter(user=user)
judge_competitions = enrollments.filter(role='judge').values_list('competition_id', flat=True)
# 基本查询:所有已提交的项目
q = Q(status='submitted')
# 加上自己创建的项目 (即使是draft)
q |= Q(contestant__user=user)
# 加上自己是评委的比赛的所有项目 (通常评委只看submitted但如果需要预审可以看draft这里假设只看submitted)
# q |= Q(competition__in=judge_competitions)
queryset = queryset.filter(q)
else:
# 未登录用户只能看已提交
queryset = queryset.filter(status='submitted')
return queryset.order_by('-final_score', '-created_at')
def perform_create(self, serializer):
user = get_current_wechat_user(self.request)
if not user:
raise serializers.ValidationError("请先登录")
competition = serializer.validated_data['competition']
# 检查是否有参赛资格
try:
enrollment = CompetitionEnrollment.objects.get(
competition=competition,
user=user,
role='contestant',
status='approved'
)
except CompetitionEnrollment.DoesNotExist:
raise serializers.ValidationError("您没有参赛资格或审核未通过")
# 检查是否已提交过项目
if Project.objects.filter(competition=competition, contestant=enrollment).exists():
raise serializers.ValidationError("您已提交过该比赛的项目,请勿重复提交")
serializer.save(contestant=enrollment)
@action(detail=True, methods=['post'])
def submit(self, request, pk=None):
"""
提交项目(从草稿转为已提交)
"""
project = self.get_object()
user = get_current_wechat_user(request)
if project.contestant.user != user:
return Response({"detail": "无权操作"}, status=status.HTTP_403_FORBIDDEN)
project.status = 'submitted'
project.save()
return Response({"status": "submitted"})
class ProjectFileViewSet(viewsets.ModelViewSet):
"""
项目附件管理
"""
serializer_class = ProjectFileSerializer
permission_classes = [permissions.AllowAny]
def get_queryset(self):
return ProjectFile.objects.all()
def perform_create(self, serializer):
# 简单权限控制:只有项目拥有者可以上传
project = serializer.validated_data['project']
user = get_current_wechat_user(self.request)
if not user or project.contestant.user != user:
raise serializers.ValidationError("无权上传文件")
serializer.save()
class ScoreViewSet(viewsets.ModelViewSet):
"""
评分管理
"""
serializer_class = ScoreSerializer
permission_classes = [permissions.AllowAny]
def get_queryset(self):
project_id = self.request.query_params.get('project')
if project_id:
return Score.objects.filter(project_id=project_id)
return Score.objects.all()
def perform_create(self, serializer):
user = get_current_wechat_user(self.request)
if not user:
raise serializers.ValidationError("请先登录")
project = serializer.validated_data['project']
# 检查是否是评委
try:
enrollment = CompetitionEnrollment.objects.get(
competition=project.competition,
user=user,
role='judge',
status='approved'
)
except CompetitionEnrollment.DoesNotExist:
raise serializers.ValidationError("您不是该比赛的评委")
# 检查是否重复打分
dimension = serializer.validated_data['dimension']
if Score.objects.filter(project=project, judge=enrollment, dimension=dimension).exists():
raise serializers.ValidationError("您已对该维度打分")
serializer.save(judge=enrollment)
class CommentViewSet(viewsets.ModelViewSet):
"""
评语管理
"""
serializer_class = CommentSerializer
permission_classes = [permissions.AllowAny]
def get_queryset(self):
project_id = self.request.query_params.get('project')
if project_id:
return Comment.objects.filter(project_id=project_id)
return Comment.objects.all()
def perform_create(self, serializer):
user = get_current_wechat_user(self.request)
if not user:
raise serializers.ValidationError("请先登录")
project = serializer.validated_data['project']
# 检查是否是评委
try:
enrollment = CompetitionEnrollment.objects.get(
competition=project.competition,
user=user,
role='judge',
status='approved'
)
except CompetitionEnrollment.DoesNotExist:
raise serializers.ValidationError("您不是该比赛的评委")
serializer.save(judge=enrollment)