from rest_framework import viewsets, permissions, status, filters from django_filters.rest_framework import DjangoFilterBackend from rest_framework.decorators import action from rest_framework.response import Response from django.utils import timezone from django.db.models import Q from .models import Article from .serializers import ( ArticleSerializer, ArticleCreateSerializer, ArticleUpdateSerializer, ArticleReviewSerializer, ArticleListSerializer ) class ArticleViewSet(viewsets.ModelViewSet): """ViewSet for Article model.""" permission_classes = [permissions.IsAuthenticatedOrReadOnly] filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend] search_fields = ['title', 'content'] filterset_fields = ['article_type', 'region', 'publish_status'] ordering_fields = ['created_at', 'updated_at', 'published_at'] ordering = ['-created_at'] def get_queryset(self): queryset = Article.objects.select_related('author', 'region', 'moderator_reviewer') # Only show published articles to non-authenticated users if not self.request.user.is_authenticated: return queryset.filter(publish_status='published') # Show all for admins if self.request.user.is_admin(): return queryset # Show own articles + published articles for regular users return queryset.filter( Q(author=self.request.user) | Q(publish_status='published') ).distinct() def get_serializer_class(self): if self.action == 'create': return ArticleCreateSerializer elif self.action in ['update', 'partial_update']: return ArticleUpdateSerializer elif self.action == 'list': return ArticleListSerializer elif self.action in ['approve', 'reject', 'submit']: return ArticleReviewSerializer return ArticleSerializer def perform_create(self, serializer): serializer.save(author=self.request.user) def perform_update(self, serializer): # Only allow updating own articles or by admin if (not self.request.user.is_admin() and str(serializer.instance.author.id) != str(self.request.user.id)): from rest_framework.exceptions import PermissionDenied raise PermissionDenied("You can only update your own articles") serializer.save() def perform_destroy(self, instance): # Only allow deleting own articles or by admin if (not self.request.user.is_admin() and str(instance.author.id) != str(self.request.user.id)): from rest_framework.exceptions import PermissionDenied raise PermissionDenied("You can only delete your own articles") instance.delete() @action(detail=True, methods=['post']) def submit(self, request, pk=None): """Submit article for review.""" article = self.get_object() if article.author != request.user: return Response( {'detail': 'You can only submit your own articles'}, status=status.HTTP_403_FORBIDDEN ) article.submit_for_review() return Response({'message': 'Article submitted for review'}) @action(detail=True, methods=['post']) def approve(self, request, pk=None): """Approve article (moderator only).""" article = self.get_object() serializer = self.get_serializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) if not request.user.is_moderator(): return Response( {'detail': 'Only moderators can approve articles'}, status=status.HTTP_403_FORBIDDEN ) # Check if moderator has permission for this region from apps.moderation.models import ModeratorPermission has_permission = ModeratorPermission.objects.filter( moderator=request.user, region=article.region, status='active' ).exists() if not has_permission: return Response( {'detail': 'You do not have permission to approve articles in this region'}, status=status.HTTP_403_FORBIDDEN ) article.approve_moderator( reviewer=request.user, reason=serializer.validated_data.get('reason', '') ) return Response({'message': 'Article approved'}) @action(detail=True, methods=['post']) def reject(self, request, pk=None): """Reject article (moderator only).""" article = self.get_object() serializer = self.get_serializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) if not request.user.is_moderator(): return Response( {'detail': 'Only moderators can reject articles'}, status=status.HTTP_403_FORBIDDEN ) # Check if moderator has permission for this region from apps.moderation.models import ModeratorPermission has_permission = ModeratorPermission.objects.filter( moderator=request.user, region=article.region, status='active' ).exists() if not has_permission: return Response( {'detail': 'You do not have permission to reject articles in this region'}, status=status.HTTP_403_FORBIDDEN ) article.reject_moderator( reviewer=request.user, reason=serializer.validated_data.get('reason', 'Required reason') ) return Response({'message': 'Article rejected'}) @action(detail=True, methods=['get']) def comments(self, request, pk=None): """Get comments for an article.""" article = self.get_object() from apps.interactions.serializers import CommentSerializer from apps.interactions.models import Comment comments = Comment.objects.filter( target_type='article', target_id=article.id, ai_status='approved' ) serializer = CommentSerializer(comments, many=True) return Response(serializer.data) @action(detail=True, methods=['post']) def like(self, request, pk=None): """Like or unlike an article.""" article = self.get_object() from apps.interactions.models import Like like, created = Like.objects.get_or_create( user=request.user, target_type='article', target_id=article.id ) if not created: like.delete() return Response({'message': 'Unliked', 'liked': False}) return Response({'message': 'Liked', 'liked': True}) @action(detail=True, methods=['get']) def stats(self, request, pk=None): """Get article statistics.""" article = self.get_object() from apps.interactions.models import Like, Comment, Rating return Response({ 'likes_count': Like.objects.filter( target_type='article', target_id=article.id ).count(), 'comments_count': Comment.objects.filter( target_type='article', target_id=article.id, ai_status='approved' ).count(), 'views_count': getattr(article, 'views_count', 0), })