from rest_framework import serializers from .models import User, Place, Review class UserSerializer(serializers.ModelSerializer): """Serializer for user registration and display.""" class Meta: model = User fields = ['id', 'name', 'phone'] read_only_fields = ['id'] def create(self, validated_data): """Create a new user with phone authentication.""" user = User.objects.create_user( phone=validated_data['phone'], name=validated_data['name'], username=validated_data['phone'] # Use phone as username ) return user class PlaceSerializer(serializers.ModelSerializer): """Serializer for place list/search results.""" average_rating = serializers.SerializerMethodField() class Meta: model = Place fields = ['id', 'name', 'address', 'average_rating'] read_only_fields = ['id'] def get_average_rating(self, obj): """Get the average rating for this place.""" return obj.average_rating class ReviewSerializer(serializers.ModelSerializer): """Serializer for reviews with user details.""" user_name = serializers.CharField(source='user.name', read_only=True) class Meta: model = Review fields = ['id', 'user_name', 'rating', 'text', 'created_at'] read_only_fields = ['id', 'user_name', 'created_at'] class PlaceDetailSerializer(serializers.ModelSerializer): """Detailed serializer for a single place with all reviews.""" average_rating = serializers.SerializerMethodField() reviews = serializers.SerializerMethodField() class Meta: model = Place fields = ['id', 'name', 'address', 'average_rating', 'reviews'] read_only_fields = ['id'] def get_average_rating(self, obj): """Get the average rating for this place.""" return obj.average_rating def get_reviews(self, obj): """ Get all reviews sorted with current user's review first, then all others sorted by newest first. """ request = self.context.get('request') if not request or not request.user.is_authenticated: reviews = obj.reviews.all() else: # Get current user's review user_review = obj.reviews.filter(user=request.user).first() # Get all other reviews other_reviews = obj.reviews.exclude(user=request.user).order_by('-created_at') # Combine: user's review first, then others if user_review: reviews = [user_review] + list(other_reviews) else: reviews = list(other_reviews) return ReviewSerializer(reviews, many=True).data class AddReviewSerializer(serializers.Serializer): """Serializer for adding a review (creates place if needed).""" place_name = serializers.CharField(max_length=255) place_address = serializers.CharField() rating = serializers.IntegerField(min_value=1, max_value=5) review_text = serializers.CharField() def validate(self, data): """Validate the review data.""" return data def create(self, validated_data): """ Create a review and associated place if it doesn't exist. Uses get_or_create to ensure atomic operation. """ user = self.context['request'].user # Get or create the place place, created = Place.objects.get_or_create( name=validated_data['place_name'], address=validated_data['place_address'] ) # Create or update the review review, created = Review.objects.update_or_create( user=user, place=place, defaults={ 'rating': validated_data['rating'], 'text': validated_data['review_text'] } ) return review