from rest_framework import serializers from .models import Service, ServiceFeature, ServiceExpertise, ServiceCategory from django.core.files.uploadedfile import InMemoryUploadedFile class ServiceFeatureSerializer(serializers.ModelSerializer): """ Serializer for ServiceFeature model """ class Meta: model = ServiceFeature fields = ['id', 'title', 'description', 'icon', 'display_order'] class ServiceExpertiseSerializer(serializers.ModelSerializer): """ Serializer for ServiceExpertise model """ class Meta: model = ServiceExpertise fields = ['id', 'title', 'description', 'icon', 'display_order'] class ServiceCategorySerializer(serializers.ModelSerializer): """ Serializer for ServiceCategory model """ class Meta: model = ServiceCategory fields = ['id', 'name', 'slug', 'description', 'display_order'] class ServiceSerializer(serializers.ModelSerializer): """ Serializer for Service model """ features = ServiceFeatureSerializer(many=True, read_only=True) expertise_items = ServiceExpertiseSerializer(many=True, read_only=True) category = ServiceCategorySerializer(read_only=True) formatted_price = serializers.ReadOnlyField() image_url = serializers.SerializerMethodField() class Meta: model = Service fields = [ 'id', 'title', 'description', 'short_description', 'slug', 'icon', 'image', 'image_url', 'price', 'formatted_price', 'category', 'duration', 'deliverables', 'technologies', 'process_steps', 'features_description', 'deliverables_description', 'process_description', 'why_choose_description', 'expertise_description', 'featured', 'display_order', 'is_active', 'created_at', 'updated_at', 'features', 'expertise_items' ] read_only_fields = ['id', 'created_at', 'updated_at', 'slug'] def get_image_url(self, obj): """Return the image URL""" return obj.get_image_url class ServiceListSerializer(serializers.ModelSerializer): """ Simplified serializer for service lists """ formatted_price = serializers.ReadOnlyField() image_url = serializers.SerializerMethodField() class Meta: model = Service fields = [ 'id', 'title', 'description', 'short_description', 'slug', 'icon', 'image', 'image_url', 'price', 'formatted_price', 'category', 'duration', 'deliverables', 'technologies', 'process_steps', 'featured', 'display_order' ] def get_image_url(self, obj): """Return the image URL""" return obj.get_image_url class ServiceCreateUpdateSerializer(serializers.ModelSerializer): """ Serializer for creating and updating services """ class Meta: model = Service fields = [ 'title', 'description', 'short_description', 'icon', 'image', 'image_url', 'price', 'category', 'duration', 'deliverables', 'technologies', 'process_steps', 'featured', 'display_order', 'is_active' ] def create(self, validated_data): # Generate slug from title if not provided if 'slug' not in validated_data: validated_data['slug'] = self.generate_unique_slug(validated_data['title']) return super().create(validated_data) def update(self, instance, validated_data): # If image is being updated, delete the old image if 'image' in validated_data and instance.image: instance.image.delete(save=False) return super().update(instance, validated_data) def generate_unique_slug(self, title): """Generate a unique slug from title""" from django.utils.text import slugify base_slug = slugify(title) slug = base_slug counter = 1 while Service.objects.filter(slug=slug).exists(): slug = f"{base_slug}-{counter}" counter += 1 return slug def validate(self, data): """Validate service data""" # Make image_url optional for existing services # Only require image or image_url for new services if self.instance is None: # Creating new service image = data.get('image') image_url = data.get('image_url') if not image and not image_url: raise serializers.ValidationError( "Either an image file or image URL must be provided for new services." ) return data