from django.contrib.auth import get_user_model from rest_framework import serializers from drf_spectacular.utils import extend_schema_field from apps.cms.models.post import ( PostCategory, PostTag, Post, PostComment, PostLike, MediaAsset, ) from apps.profiles.models.institution import Institution User = get_user_model() class PostCategorySerializer(serializers.ModelSerializer): posts_count = serializers.SerializerMethodField() class Meta: model = PostCategory fields = [ 'id', 'name', 'slug', 'language', 'description', 'created_at', 'posts_count', ] read_only_fields = ['id', 'slug', 'created_at', 'posts_count'] @extend_schema_field(serializers.IntegerField) def get_posts_count(self, obj) -> int: return obj.posts.filter(status=Post.Status.PUBLISHED).count() class PostTagSerializer(serializers.ModelSerializer): class Meta: model = PostTag fields = ['id', 'name', 'slug'] read_only_fields = ['id', 'slug'] class PostAuthorMiniSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'email', 'fullname', 'avatar'] read_only_fields = fields class PostInstitutionMiniSerializer(serializers.ModelSerializer): type_display = serializers.CharField(source='get_type_display', read_only=True) class Meta: model = Institution fields = ['id', 'name', 'slug', 'type', 'type_display', 'avatar', 'city', 'country'] read_only_fields = fields class PostCommentSerializer(serializers.ModelSerializer): user = PostAuthorMiniSerializer(read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = PostComment fields = [ 'id', 'post', 'user', 'author_name', 'author_email', 'content', 'status', 'status_display', 'created_at', ] read_only_fields = ['id', 'post', 'user', 'status', 'status_display', 'created_at'] class PostCommentCreateSerializer(serializers.Serializer): content = serializers.CharField(required=True) author_name = serializers.CharField(required=False, allow_blank=True, max_length=255) author_email = serializers.EmailField(required=False, allow_blank=True) class PostListSerializer(serializers.ModelSerializer): post_type_display = serializers.CharField(source='get_post_type_display', read_only=True) category_name = serializers.CharField(source='category.name', read_only=True, allow_null=True) author = PostAuthorMiniSerializer(read_only=True) institution = PostInstitutionMiniSerializer(read_only=True) comments_count = serializers.SerializerMethodField() is_liked = serializers.SerializerMethodField() class Meta: model = Post fields = [ 'id', 'title', 'slug', 'post_type', 'post_type_display', 'category', 'category_name', 'language', 'status', 'author', 'institution', 'author_role_label', 'author_custom_avatar', 'featured_image', 'excerpt', 'tags', 'reading_time_minutes', 'views_count', 'likes_count', 'comments_count', 'is_featured', 'publish_date', 'is_liked', 'created_at', ] read_only_fields = fields @extend_schema_field(serializers.IntegerField) def get_comments_count(self, obj) -> int: return obj.comments.filter(status=PostComment.Status.APPROVED).count() @extend_schema_field(serializers.BooleanField) def get_is_liked(self, obj) -> bool: request = self.context.get('request') if not request or not request.user.is_authenticated: return False return obj.is_liked_by(request.user) class PostDetailSerializer(serializers.ModelSerializer): post_type_display = serializers.CharField(source='get_post_type_display', read_only=True) category = PostCategorySerializer(read_only=True) author = PostAuthorMiniSerializer(read_only=True) institution = PostInstitutionMiniSerializer(read_only=True) comments = serializers.SerializerMethodField() comments_count = serializers.SerializerMethodField() is_liked = serializers.SerializerMethodField() class Meta: model = Post fields = [ 'id', 'title', 'slug', 'post_type', 'post_type_display', 'category', 'language', 'status', 'author', 'institution', 'author_role_label', 'author_custom_avatar', 'featured_image', 'excerpt', 'content', 'tags', 'reading_time_minutes', 'views_count', 'likes_count', 'comments_count', 'is_featured', 'publish_date', 'is_liked', 'comments', 'created_at', 'updated_at', ] read_only_fields = [ 'id', 'slug', 'reading_time_minutes', 'views_count', 'likes_count', 'comments_count', 'is_liked', 'comments', 'created_at', 'updated_at', ] @extend_schema_field(PostCommentSerializer(many=True)) def get_comments(self, obj): approved_comments = obj.comments.filter(status=PostComment.Status.APPROVED).order_by('-created_at') return PostCommentSerializer(approved_comments, many=True).data @extend_schema_field(serializers.IntegerField) def get_comments_count(self, obj) -> int: return obj.comments.filter(status=PostComment.Status.APPROVED).count() @extend_schema_field(serializers.BooleanField) def get_is_liked(self, obj) -> bool: request = self.context.get('request') if not request or not request.user.is_authenticated: return False return obj.is_liked_by(request.user) class PostCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = Post fields = [ 'title', 'post_type', 'category', 'language', 'status', 'institution', 'author_role_label', 'author_custom_avatar', 'featured_image', 'excerpt', 'content', 'tags', 'is_featured', 'publish_date', ] def create(self, validated_data): request = self.context.get('request') if request and request.user.is_authenticated: validated_data['author'] = request.user return super().create(validated_data) class PostLikeResponseSerializer(serializers.Serializer): is_liked = serializers.BooleanField() likes_count = serializers.IntegerField() message = serializers.CharField() class MediaAssetSerializer(serializers.ModelSerializer): media_type_display = serializers.CharField(source='get_media_type_display', read_only=True) uploaded_by_email = serializers.EmailField(source='uploaded_by.email', read_only=True, allow_null=True) class Meta: model = MediaAsset fields = [ 'id', 'file', 'title', 'media_type', 'media_type_display', 'file_size', 'dimensions', 'uploaded_by_email', 'created_at', ] read_only_fields = ['id', 'media_type_display', 'file_size', 'uploaded_by_email', 'created_at'] def create(self, validated_data): request = self.context.get('request') if request and request.user.is_authenticated: validated_data['uploaded_by'] = request.user return super().create(validated_data)