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)