Files
blog.pyaqa.ru/app/application/dtos/post.py
Sergey Vanyushkin 7ff3fa0992
All checks were successful
ci/woodpecker/pr/pipeline Pipeline was successful
feat: add comments feature with nested replies and recursive rendering
Implement full comments system: domain entities (Comment, CommentLike),
value objects (CommentContent), use cases (CRUD, like toggle), SQLAlchemy
repository, API v1 endpoints, web UI with comment form and nested replies,
i18n translations (EN/RU/FR/DE), and E2E tests.

Fix nested reply (reply-to-reply) not displaying — the flat reply_comments
dict was only queried for top-level comment IDs, so deeply nested replies
were saved to DB (incrementing comment count) but never rendered. Switch
to a recursive Jinja2 macro that renders any nesting depth.
2026-05-11 15:34:20 +03:00

105 lines
2.5 KiB
Python

"""DTOs for post use cases.
This module defines Data Transfer Objects used for communication between
application layer use cases and presentation layer. DTOs are immutable
dataclasses that carry data across process boundaries.
"""
from dataclasses import dataclass
from datetime import datetime
from uuid import UUID
@dataclass(frozen=True)
class CreatePostDTO:
"""DTO for creating a post.
Carries post creation data from API to use case.
Contains all required fields for post creation.
Attributes:
title: Post title string.
content: Post content string.
author_id: Identifier of the post author.
tags: Optional list of tags for categorization.
Example:
>>> dto = CreatePostDTO(
... title="My Post",
... content="Content here...",
... author_id="user-123",
... tags=["python"]
... )
"""
title: str
content: str
author_id: str
tags: list[str] | None = None
@dataclass(frozen=True)
class UpdatePostDTO:
"""DTO for updating a post.
Carries optional post update data. All fields are optional
allowing partial updates.
Attributes:
title: Optional new title.
content: Optional new content.
tags: Optional new tags list.
Example:
>>> dto = UpdatePostDTO(title="Updated Title")
"""
title: str | None = None
content: str | None = None
tags: list[str] | None = None
@dataclass(frozen=True)
class PostResponseDTO:
"""DTO for post response.
Carries complete post data for API responses.
Includes all post attributes and metadata.
Attributes:
id: Unique post identifier.
title: Post title.
content: Post content.
slug: URL-friendly slug.
author_id: Author identifier.
published: Publication status.
tags: List of tags.
created_at: Creation timestamp.
updated_at: Last update timestamp.
Example:
>>> dto = PostResponseDTO(
... id=uuid,
... title="Post",
... content="...",
... slug="post",
... author_id="user-123",
... published=True,
... tags=[],
... created_at=datetime.now(),
... updated_at=datetime.now()
... )
"""
id: UUID
title: str
content: str
slug: str
author_id: str
published: bool
tags: list[str]
created_at: datetime
updated_at: datetime
like_count: int = 0
comment_count: int = 0