from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from apps.skills.serializers import SkillSerializer from .models import Resource, ResourceCheckpoint, SkillResource class ResourceCheckpointSerializer(serializers.ModelSerializer): # Populated when the serializer context carries a `completed_checkpoint_ids` # set — e.g. ResourceDetailView preloads the current user's completed # checkpoint IDs for the fetched resource. Absent in contexts without a # user (schema generation, seed scripts) — falls back to False. is_completed = serializers.SerializerMethodField() class Meta: model = ResourceCheckpoint fields = ['id', 'order_index', 'title', 'url_fragment', 'estimated_minutes', 'source', 'is_completed'] def get_is_completed(self, obj) -> bool: completed = self.context.get('completed_checkpoint_ids') or set() return obj.id in completed class SkillResourceSerializer(serializers.ModelSerializer): skill = SkillSerializer(read_only=True) class Meta: model = SkillResource fields = ['skill', 'relevance_score'] class ResourceListSerializer(serializers.ModelSerializer): # Populated by an Exists() annotation on the view's queryset — see # ResourceListView. Keep as BooleanField so it fails loud if the view # ever forgets the annotation. has_checkpoints = serializers.BooleanField(read_only=True) class Meta: model = Resource fields = ['id', 'title', 'provider', 'url', 'difficulty_level', 'duration', 'type', 'rating', 'has_checkpoints'] class ResourceDetailSerializer(serializers.ModelSerializer): checkpoints = ResourceCheckpointSerializer(many=True, read_only=True) skill_mappings = serializers.SerializerMethodField() class Meta: model = Resource fields = ['id', 'title', 'provider', 'url', 'difficulty_level', 'duration', 'type', 'rating', 'checkpoints', 'skill_mappings'] @extend_schema_field(SkillResourceSerializer(many=True)) def get_skill_mappings(self, obj): return SkillResourceSerializer( SkillResource.objects.filter(resource=obj).select_related('skill'), many=True, ).data class ResourceAdminSerializer(serializers.ModelSerializer): """Full-field writable Resource serializer for admin CRUD. Linked skills and checkpoints are managed via separate endpoints (SkillResourceAdminViewSet, ResourceCheckpointAdminViewSet) so that each concern has its own CRUD surface — matches the existing Django admin UX. """ class Meta: model = Resource fields = ['id', 'title', 'provider', 'url', 'difficulty_level', 'duration', 'type', 'rating', 'created_at'] read_only_fields = ['created_at'] class ResourceCheckpointAdminSerializer(serializers.ModelSerializer): class Meta: model = ResourceCheckpoint fields = ['id', 'resource', 'order_index', 'title', 'url_fragment', 'estimated_minutes', 'source', 'extracted_at'] class SkillResourceAdminSerializer(serializers.ModelSerializer): skill_detail = SkillSerializer(source='skill', read_only=True) class Meta: model = SkillResource fields = ['id', 'skill', 'skill_detail', 'resource', 'relevance_score']