You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

263 lines
8.0 KiB

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)