feat: updated CLAUDE.md
This commit is contained in:
73
CLAUDE.md
73
CLAUDE.md
@@ -7,9 +7,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
This is a FastAPI + Telegram Bot backend application for managing Telegram channel integrations. The project uses:
|
This is a FastAPI + Telegram Bot backend application for managing Telegram channel integrations. The project uses:
|
||||||
- **FastAPI** for HTTP API endpoints
|
- **FastAPI** for HTTP API endpoints
|
||||||
- **aiogram** for Telegram bot functionality
|
- **aiogram** for Telegram bot functionality
|
||||||
- **SQLAlchemy 2.0** (async) for database operations
|
- **Tortoise ORM** (async) for database operations
|
||||||
- **PostgreSQL** with asyncpg driver
|
- **PostgreSQL** with asyncpg driver
|
||||||
- **Alembic** for database migrations
|
- **aerich** for database migrations
|
||||||
- **uv** for Python package management
|
- **uv** for Python package management
|
||||||
|
|
||||||
## Development Commands
|
## Development Commands
|
||||||
@@ -23,7 +23,7 @@ uv sync
|
|||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
# Run database migrations
|
# Run database migrations
|
||||||
uv run alembic upgrade head
|
make migrate-up # or: export $(cat .env | xargs) && aerich upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running the Application
|
### Running the Application
|
||||||
@@ -58,14 +58,19 @@ uv run pytest tests/test_file.py::test_function_name
|
|||||||
|
|
||||||
### Database Migrations
|
### Database Migrations
|
||||||
```bash
|
```bash
|
||||||
# Create a new migration
|
# Create a new migration (auto-generated based on model changes)
|
||||||
uv run alembic revision --autogenerate -m "description"
|
make migrate-create # or: export $(cat .env | xargs) && aerich migrate
|
||||||
|
|
||||||
# Apply migrations
|
# Apply migrations
|
||||||
uv run alembic upgrade head
|
make migrate-up # or: export $(cat .env | xargs) && aerich upgrade
|
||||||
|
|
||||||
# Rollback one migration
|
# Rollback one migration
|
||||||
uv run alembic downgrade -1
|
make migrate-down # or: export $(cat .env | xargs) && aerich downgrade
|
||||||
|
|
||||||
|
# NOTE: For custom constraints (CHECK, custom indexes, etc.) that cannot be defined
|
||||||
|
# in Tortoise ORM models, create empty migrations and edit them manually:
|
||||||
|
export $(cat .env | xargs) && aerich migrate --name "add_check_constraint" --empty
|
||||||
|
# Then edit the created file and add `# ruff: noqa` and `# mypy: ignore-errors` at the top.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
@@ -75,12 +80,12 @@ uv run alembic downgrade -1
|
|||||||
The codebase follows a clean architecture pattern with clear separation of concerns:
|
The codebase follows a clean architecture pattern with clear separation of concerns:
|
||||||
|
|
||||||
1. **Domain Layer** (`src/domain/`)
|
1. **Domain Layer** (`src/domain/`)
|
||||||
- SQLAlchemy ORM models that represent database entities
|
- Tortoise ORM models that represent database entities
|
||||||
- All models inherit from `domain.Base` which provides:
|
- All models inherit from `domain.base.TimestampedModel` which provides:
|
||||||
- Auto-generated `id` (UUID primary key)
|
- Auto-generated `id` (UUID primary key)
|
||||||
- Timestamps: `created_at`, `updated_at`, `deleted_at`
|
- Timestamps: `created_at`, `updated_at`, `deleted_at`
|
||||||
- Automatic table naming (pluralized lowercase class name)
|
|
||||||
- Timezone-aware datetime fields
|
- Timezone-aware datetime fields
|
||||||
|
- Use `class Meta: table = 'table_name'` for explicit table naming
|
||||||
|
|
||||||
2. **Use Case Layer** (`src/usecase/`)
|
2. **Use Case Layer** (`src/usecase/`)
|
||||||
- Business logic functions organized by feature
|
- Business logic functions organized by feature
|
||||||
@@ -322,17 +327,55 @@ await self.telegram_bot.send_message_with_inline_keyboard('Message', chat_id, bu
|
|||||||
**Типизация Enum в Domain:**
|
**Типизация Enum в Domain:**
|
||||||
- Используйте `enum.StrEnum` для строковых enum (Python 3.11+)
|
- Используйте `enum.StrEnum` для строковых enum (Python 3.11+)
|
||||||
- Enum значения в lowercase с underscores
|
- Enum значения в lowercase с underscores
|
||||||
- Передавайте enum в SQLAlchemy через `Enum(EnumClass)`
|
- Используйте `fields.CharEnumField()` в Tortoise ORM
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import enum
|
import enum
|
||||||
from sqlalchemy import Enum
|
from tortoise import fields
|
||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from .base import TimestampedModel
|
||||||
|
|
||||||
class TelegramStateEnum(enum.StrEnum):
|
class TelegramStateEnum(enum.StrEnum):
|
||||||
CREATIVE_WAITING_CHANNEL = 'creative_waiting_channel'
|
CREATIVE_WAITING_CHANNEL = 'creative_waiting_channel'
|
||||||
CREATIVE_WAITING_NAME = 'creative_waiting_name'
|
CREATIVE_WAITING_NAME = 'creative_waiting_name'
|
||||||
|
|
||||||
class TelegramState(Base):
|
class TelegramState(TimestampedModel):
|
||||||
state: Mapped[TelegramStateEnum] = mapped_column(Enum(TelegramStateEnum), nullable=False)
|
state = fields.CharEnumField(TelegramStateEnum, max_length=26)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table = 'telegram_state'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Database Constraints:**
|
||||||
|
- Foreign keys: Use `fields.ForeignKeyField()` with `on_delete=fields.CASCADE`
|
||||||
|
- Unique constraints: Use `unique=True` or `unique_together` in Meta
|
||||||
|
- CHECK constraints: Cannot be defined in Tortoise models - create manual migrations
|
||||||
|
- Indexes: Use `index=True` on fields or define in Meta
|
||||||
|
|
||||||
|
Example with CHECK constraint:
|
||||||
|
```bash
|
||||||
|
# Create empty migration
|
||||||
|
export $(cat .env | xargs) && aerich migrate --name "add_check_constraint" --empty
|
||||||
|
```
|
||||||
|
|
||||||
|
Then edit the created file:
|
||||||
|
```python
|
||||||
|
# migrations/models/1_xxx_add_check_constraint.py
|
||||||
|
# ruff: noqa
|
||||||
|
# mypy: ignore-errors
|
||||||
|
from tortoise import BaseDBAsyncClient
|
||||||
|
|
||||||
|
RUN_IN_TRANSACTION = True
|
||||||
|
|
||||||
|
async def upgrade(db: BaseDBAsyncClient) -> str:
|
||||||
|
return """
|
||||||
|
ALTER TABLE "table_name"
|
||||||
|
ADD CONSTRAINT "constraint_name"
|
||||||
|
CHECK (your_condition);
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def downgrade(db: BaseDBAsyncClient) -> str:
|
||||||
|
return """
|
||||||
|
ALTER TABLE "table_name"
|
||||||
|
DROP CONSTRAINT IF EXISTS "constraint_name";
|
||||||
|
"""
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user