"""Blog API schemas.""" from ninja import Schema, ModelSchema from typing import Optional, List from datetime import datetime from apps.blog.models import Category, Tag, Comment from core.media import PREVIEW_VARIANT, THUMBNAIL_VARIANT, derivative_url class CategorySchema(ModelSchema): class Config: model = Category model_fields = ['id', 'name', 'slug', 'description'] class TagSchema(ModelSchema): class Config: model = Tag model_fields = ['id', 'name', 'slug'] class AuthorSchema(Schema): id: int username: str first_name: str last_name: str profile_picture: Optional[str] = None profile_picture_thumbnail_url: Optional[str] = None profile_picture_preview_url: Optional[str] = None @staticmethod def resolve_profile_picture(obj, context): request = context['request'] if obj.profile_picture and hasattr(obj.profile_picture, 'url'): return request.build_absolute_uri(obj.profile_picture.url) return None @staticmethod def resolve_profile_picture_thumbnail_url(obj, context): request = context["request"] url = derivative_url(obj.profile_picture, THUMBNAIL_VARIANT) return request.build_absolute_uri(url) if url else None @staticmethod def resolve_profile_picture_preview_url(obj, context): request = context["request"] url = derivative_url(obj.profile_picture, PREVIEW_VARIANT) return request.build_absolute_uri(url) if url else None class PostListSchema(Schema): id: int title: str slug: str excerpt: str author: AuthorSchema featured_image: Optional[str] = None absolute_featured_image_url: Optional[str] = None absolute_featured_image_thumbnail_url: Optional[str] = None absolute_featured_image_preview_url: Optional[str] = None status: str published_at: Optional[datetime] = None category: Optional[CategorySchema] = None tags: List[TagSchema] is_featured: bool created_at: datetime reading_time: int @staticmethod def resolve_absolute_featured_image_url(obj, context): request = context["request"] if obj.featured_image and hasattr(obj.featured_image, "url"): return request.build_absolute_uri(obj.featured_image.url) return None @staticmethod def resolve_absolute_featured_image_thumbnail_url(obj, context): request = context["request"] url = derivative_url(obj.featured_image, THUMBNAIL_VARIANT) return request.build_absolute_uri(url) if url else None @staticmethod def resolve_absolute_featured_image_preview_url(obj, context): request = context["request"] url = derivative_url(obj.featured_image, PREVIEW_VARIANT) return request.build_absolute_uri(url) if url else None class PostDetailSchema(PostListSchema): content: str content_html: str class PostCreateSchema(Schema): title: str content: str excerpt: Optional[str] = None category_id: Optional[int] = None tag_ids: Optional[List[int]] = [] status: str = "draft" is_featured: bool = False class CommentSchema(ModelSchema): author: AuthorSchema replies: List['CommentSchema'] = [] post_id: int post_title: str post_slug: str class Config: model = Comment model_fields = ['id', 'content', 'created_at', 'is_approved'] @staticmethod def resolve_post_id(obj): return obj.post_id @staticmethod def resolve_post_title(obj): return obj.post.title @staticmethod def resolve_post_slug(obj): return obj.post.slug class CommentCreateSchema(Schema): content: str parent_id: Optional[int] = None