- Django 4.2 + DRF + JWT + GraphQL - React 18 + MobX + styled-components - PostgreSQL 数据库 - Docker + Docker Compose + Nginx - 完整的功能模块(用户、版块、文章、服务、交互、版主管理) - 完整的文档(需求、部署、测试)
141 lines
5.5 KiB
Python
141 lines
5.5 KiB
Python
from rest_framework import viewsets, permissions, filters
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
from django.shortcuts import get_object_or_404
|
|
from .models import Region
|
|
from .serializers import (
|
|
RegionSerializer,
|
|
RegionDetailSerializer,
|
|
RegionTreeSerializer
|
|
)
|
|
from apps.interactions.models import Rating, Favorite
|
|
|
|
|
|
class RegionViewSet(viewsets.ModelViewSet):
|
|
"""ViewSet for Region model."""
|
|
|
|
queryset = Region.objects.filter(status='active')
|
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
|
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
|
|
search_fields = ['name']
|
|
ordering_fields = ['name', 'level', 'created_at']
|
|
ordering = ['level', 'name']
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == 'retrieve':
|
|
return RegionDetailSerializer
|
|
elif self.action == 'tree':
|
|
return RegionTreeSerializer
|
|
return RegionSerializer
|
|
|
|
def perform_create(self, serializer):
|
|
# Only admin can create regions
|
|
if not self.request.user.is_admin():
|
|
from rest_framework.exceptions import PermissionDenied
|
|
raise PermissionDenied("Only admins can create regions")
|
|
serializer.save()
|
|
|
|
def perform_update(self, serializer):
|
|
# Only admin can update regions
|
|
if not self.request.user.is_admin():
|
|
from rest_framework.exceptions import PermissionDenied
|
|
raise PermissionDenied("Only admins can update regions")
|
|
serializer.save()
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def provinces(self, request):
|
|
"""Get all provinces (top-level regions)."""
|
|
provinces = self.queryset.filter(parent__isnull=True)
|
|
serializer = self.get_serializer(provinces, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def children(self, request, pk=None):
|
|
"""Get children of a region."""
|
|
region = self.get_object()
|
|
children = region.get_children()
|
|
serializer = self.get_serializer(children, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def path(self, request, pk=None):
|
|
"""Get full path of a region."""
|
|
region = self.get_object()
|
|
path = []
|
|
current = region
|
|
while current:
|
|
serializer = self.get_serializer(current)
|
|
path.insert(0, serializer.data)
|
|
current = current.parent
|
|
return Response(path)
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def tree(self, request):
|
|
"""Get region tree structure."""
|
|
root_regions = self.queryset.filter(parent__isnull=True)
|
|
serializer = RegionTreeSerializer(root_regions, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def articles(self, request, pk=None):
|
|
"""Get articles for a region."""
|
|
region = self.get_object()
|
|
articles = region.articles.filter(publish_status='published')
|
|
from apps.articles.serializers import ArticleListSerializer
|
|
serializer = ArticleListSerializer(articles, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def services(self, request, pk=None):
|
|
"""Get featured services for a region."""
|
|
region = self.get_object()
|
|
services = region.featured_services.filter(publish_status='published')
|
|
from apps.featured_services.serializers import FeaturedServiceListSerializer
|
|
serializer = FeaturedServiceListSerializer(services, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def stats(self, request, pk=None):
|
|
"""Get statistics for a region."""
|
|
region = self.get_object()
|
|
return Response({
|
|
'articles_count': region.articles.filter(publish_status='published').count(),
|
|
'services_count': region.featured_services.filter(publish_status='published').count(),
|
|
'children_count': region.children.count(),
|
|
})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def rate(self, request, pk=None):
|
|
"""Rate a region."""
|
|
region = self.get_object()
|
|
serializer = RatingCreateSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
serializer.save(target_type='region', target_id=region.id)
|
|
return Response({'message': 'Rating saved'}, status=201)
|
|
return Response(serializer.errors, status=400)
|
|
|
|
@action(detail=True, methods=['get'])
|
|
def my_rating(self, request, pk=None):
|
|
"""Get user's rating for a region."""
|
|
region = self.get_object()
|
|
try:
|
|
rating = Rating.objects.get(
|
|
user=request.user,
|
|
target_type='region',
|
|
target_id=region.id
|
|
)
|
|
return Response({'score': rating.score})
|
|
except Rating.DoesNotExist:
|
|
return Response({'score': None})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def favorite(self, request, pk=None):
|
|
"""Favorite or unfavorite a region."""
|
|
region = self.get_object()
|
|
serializer = FavoriteCreateSerializer(data=request.data)
|
|
if serializer.is_valid():
|
|
result = serializer.save(target_type='region', target_id=region.id)
|
|
if result is None:
|
|
return Response({'message': 'Unfavorited'}, status=200)
|
|
return Response({'message': 'Favorited'}, status=201)
|
|
return Response(serializer.errors, status=400) |