Initial commit: React + Django 城市手册项目
- Django 4.2 + DRF + JWT + GraphQL - React 18 + MobX + styled-components - PostgreSQL 数据库 - Docker + Docker Compose + Nginx - 完整的功能模块(用户、版块、文章、服务、交互、版主管理) - 完整的文档(需求、部署、测试)
This commit is contained in:
197
backend/apps/moderation/views.py
Normal file
197
backend/apps/moderation/views.py
Normal file
@@ -0,0 +1,197 @@
|
||||
from rest_framework import viewsets, permissions, status, filters
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from django.db.models import Q
|
||||
from .models import (
|
||||
ModeratorApplication,
|
||||
ModeratorPermission,
|
||||
ModeratorSupport,
|
||||
PermissionRestriction
|
||||
)
|
||||
from .serializers import (
|
||||
ModeratorApplicationSerializer,
|
||||
ModeratorApplicationCreateSerializer,
|
||||
ModeratorPermissionSerializer,
|
||||
ModeratorSupportSerializer,
|
||||
PermissionRestrictionSerializer
|
||||
)
|
||||
|
||||
|
||||
class ModeratorApplicationViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for ModeratorApplication model."""
|
||||
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [filters.SearchFilter, filters.OrderingFilter, filters.DjangoFilterBackend]
|
||||
search_fields = ['applicant__username', 'region__name']
|
||||
filterset_fields = ['status', 'rank', 'region']
|
||||
ordering_fields = ['created_at', 'deadline']
|
||||
ordering = ['-created_at']
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = ModeratorApplication.objects.select_related('applicant', 'region', 'reviewed_by')
|
||||
|
||||
# Admins see all
|
||||
if self.request.user.is_admin():
|
||||
return queryset
|
||||
|
||||
# Regular users see their own applications
|
||||
return queryset.filter(applicant=self.request.user)
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return ModeratorApplicationCreateSerializer
|
||||
return ModeratorApplicationSerializer
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save()
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def support(self, request, pk=None):
|
||||
"""Support a moderator application."""
|
||||
application = self.get_object()
|
||||
|
||||
# Check if application is still pending
|
||||
if application.status != 'pending':
|
||||
return Response(
|
||||
{'detail': 'Can only support pending applications'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Check if already supported
|
||||
if ModeratorSupport.objects.filter(
|
||||
supporter=request.user,
|
||||
application=application
|
||||
).exists():
|
||||
return Response(
|
||||
{'detail': 'Already supported this application'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
serializer = ModeratorSupportSerializer(data={'application': application.id})
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response({'message': 'Application supported', 'support_count': application.support_count})
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def approve(self, request, pk=None):
|
||||
"""Approve moderator application (admin only)."""
|
||||
if not request.user.is_admin():
|
||||
return Response(
|
||||
{'detail': 'Only admins can approve applications'},
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
|
||||
application = self.get_object()
|
||||
|
||||
if application.status != 'pending':
|
||||
return Response(
|
||||
{'detail': 'Can only approve pending applications'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Check if has enough support
|
||||
if not application.has_enough_support():
|
||||
return Response(
|
||||
{'detail': 'Not enough support votes'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Create moderator permission
|
||||
from .models import ModeratorPermission
|
||||
ModeratorPermission.objects.create(
|
||||
moderator=application.applicant,
|
||||
region=application.region,
|
||||
rank=application.rank,
|
||||
status='active'
|
||||
)
|
||||
|
||||
# Update application status
|
||||
application.status = 'approved'
|
||||
application.reviewed_by = request.user
|
||||
application.reviewed_at = timezone.now()
|
||||
application.save()
|
||||
|
||||
return Response({'message': 'Application approved, moderator permissions granted'})
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def reject(self, request, pk=None):
|
||||
"""Reject moderator application (admin only)."""
|
||||
if not request.user.is_admin():
|
||||
return Response(
|
||||
{'detail': 'Only admins can reject applications'},
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
|
||||
application = self.get_object()
|
||||
|
||||
if application.status != 'pending':
|
||||
return Response(
|
||||
{'detail': 'Can only reject pending applications'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
application.status = 'rejected'
|
||||
application.reviewed_by = request.user
|
||||
application.reviewed_at = timezone.now()
|
||||
application.save()
|
||||
|
||||
return Response({'message': 'Application rejected'})
|
||||
|
||||
@action(detail=False, methods=['get'])
|
||||
def my_applications(self, request):
|
||||
"""Get current user's applications."""
|
||||
applications = ModeratorApplication.objects.filter(
|
||||
applicant=request.user
|
||||
).select_related('region')
|
||||
serializer = self.get_serializer(applications, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class ModeratorPermissionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""ViewSet for ModeratorPermission model (read-only)."""
|
||||
|
||||
queryset = ModeratorPermission.objects.select_related('moderator', 'region')
|
||||
serializer_class = ModeratorPermissionSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
# Admins see all
|
||||
if self.request.user.is_admin():
|
||||
return self.queryset
|
||||
|
||||
# Moderators see their own permissions
|
||||
return self.queryset.filter(moderator=self.request.user)
|
||||
|
||||
@action(detail=False, methods=['get'])
|
||||
def my_permissions(self, request):
|
||||
"""Get current user's moderator permissions."""
|
||||
permissions = ModeratorPermission.objects.filter(
|
||||
moderator=request.user,
|
||||
status='active'
|
||||
).select_related('region')
|
||||
serializer = self.get_serializer(permissions, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class PermissionRestrictionViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for PermissionRestriction model."""
|
||||
|
||||
queryset = PermissionRestriction.objects.select_related('operator', 'target_moderator')
|
||||
serializer_class = PermissionRestrictionSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
# Admins see all
|
||||
if self.request.user.is_admin():
|
||||
return self.queryset
|
||||
|
||||
# Moderators see restrictions on themselves
|
||||
return self.queryset.filter(target_moderator=self.request.user)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
# Only admins can create restrictions
|
||||
if not self.request.user.is_admin():
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
raise PermissionDenied("Only admins can create restrictions")
|
||||
serializer.save(operator=self.request.user)
|
||||
Reference in New Issue
Block a user