mirror of
https://github.com/barkeser2002/offline-db.git
synced 2026-09-25 03:40:05 +03:00
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
64 lines
2.4 KiB
Python
64 lines
2.4 KiB
Python
import bleach
|
|
from rest_framework import serializers, viewsets, permissions, status
|
|
from rest_framework.response import Response
|
|
from rest_framework.throttling import UserRateThrottle
|
|
from django.db import IntegrityError
|
|
from ..models import Review, Anime
|
|
|
|
class ReviewCreateThrottle(UserRateThrottle):
|
|
scope = 'review'
|
|
def allow_request(self, request, view):
|
|
if request.method != 'POST':
|
|
return True
|
|
return super().allow_request(request, view)
|
|
|
|
class IsOwnerOrReadOnly(permissions.BasePermission):
|
|
"""
|
|
Custom permission to only allow owners of an object to edit or delete it.
|
|
"""
|
|
def has_object_permission(self, request, view, obj):
|
|
# Read permissions are allowed to any request,
|
|
# so we'll always allow GET, HEAD or OPTIONS requests.
|
|
if request.method in permissions.SAFE_METHODS:
|
|
return True
|
|
|
|
# Write permissions are only allowed to the owner of the review.
|
|
return obj.user == request.user
|
|
|
|
class ReviewSerializer(serializers.ModelSerializer):
|
|
user = serializers.StringRelatedField(read_only=True)
|
|
|
|
class Meta:
|
|
model = Review
|
|
fields = ['id', 'user', 'anime', 'rating', 'text', 'created_at']
|
|
read_only_fields = ['user', 'created_at']
|
|
|
|
def validate_text(self, value):
|
|
# Sanitize HTML input using bleach
|
|
return bleach.clean(value, tags=[], strip=True)
|
|
|
|
def create(self, validated_data):
|
|
validated_data['user'] = self.context['request'].user
|
|
return super().create(validated_data)
|
|
|
|
class ReviewViewSet(viewsets.ModelViewSet):
|
|
# Optimization: Use select_related('user') to avoid N+1 queries when serializing the user field
|
|
queryset = Review.objects.select_related('user').all().order_by('-created_at')
|
|
serializer_class = ReviewSerializer
|
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
|
|
throttle_classes = [ReviewCreateThrottle]
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
try:
|
|
return super().create(request, *args, **kwargs)
|
|
except IntegrityError:
|
|
return Response(
|
|
{"detail": "You have already reviewed this anime."},
|
|
status=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
|
|
def perform_create(self, serializer):
|
|
user = self.request.user
|
|
serializer.save(user=user)
|
|
# Note: Critic badge check is handled automatically via post_save signal in users.signals
|