Перейти к содержанию

Модели

Модель — это Python-класс, наследующий DotModel. Каждая модель соответствует одной таблице в базе данных.

Определение модели

backend/base/crm/chat/models/chat_message.py
from backend.base.system.dotorm.dotorm.model import DotModel
from backend.base.system.dotorm.dotorm.fields import (
    Integer, Char, Text, Boolean, Datetime, Many2one
)


class ChatMessage(DotModel):
    __table__ = "chat_messages"       # (1)!
    __route__ = "chat_messages"       # (2)!

    chat_id: "Chat" = Many2one["Chat"](    # (3)!
        relation_table="chats",
        required=True,
    )
    author_user_id: "User" = Many2one["User"](
        relation_table="users",
        required=True,
    )
    body: str = Text()
    is_edited: bool = Boolean(default=False)
    is_deleted: bool = Boolean(default=False)
    pinned: bool = Boolean(default=False)
    is_read: bool = Boolean(default=True)
    reply_to_id: "ChatMessage | None" = Many2one["ChatMessage"](
        relation_table="chat_messages",
    )
  1. Имя таблицы в базе данных. Обязательное поле.
  2. Имя для авто-генерированного CRUD роута (/chat_messages/search, /chat_messages/create, ...). По умолчанию равно __table__.
  3. Внешний ключ. Генерирует колонку chat_id INTEGER REFERENCES chats(id).

Мета-атрибуты

Атрибут Тип По умолчанию Описание
__table__ str Имя таблицы в БД (обязательно)
__route__ str __table__ Префикс REST API роута
__access__ dict {} Правила доступа (ACL)

Встроенные поля

Каждая модель автоматически получает поле id:

class DotModel:
    id: int = Integer(primary_key=True)  # AUTO INCREMENT

id всегда есть

Не нужно определять id в модели — он наследуется из DotModel.

Регистрация модели

Модель регистрируется в project_setup.py:

backend/project_setup.py
class Models(ModelsCore):
    chat = Chat
    chat_message = ChatMessage
    chat_member = ChatMember

После регистрации модель доступна через env.models.chat_message и автоматически получает:

  • CRUD API роуты (/chat_messages/search, /chat_messages/create, ...)
  • Pydantic-схемы валидации
  • DDL для создания таблицы

Создание экземпляра

Экземпляр модели — это набор данных, а не ORM-запись. Он используется как payload для create() и update():

# Payload для создания (не сохранённый в БД)
msg = ChatMessage(
    chat_id=1,
    author_user_id=42,
    body="Hello!",
)

# Сохранение → получаем id
msg_id = await ChatMessage.create(msg)

# Загрузка из БД → полноценная запись
msg = await ChatMessage.get(msg_id)
msg.body       # "Hello!"
msg.is_edited  # False (default)
msg.id         # msg_id

Classmethod vs Instance

Метод Тип Описание
Model.create(payload) classmethod Создать запись
Model.get(id) classmethod Получить по ID
Model.search(...) classmethod Поиск с фильтрами
record.update(payload) instance Обновить запись
record.delete() instance Удалить запись
# Classmethod — вызывается на классе
chat = await Chat.get(1)
chats = await Chat.search(filter=[("is_archived", "=", False)])

# Instance — вызывается на загруженной записи
await chat.update(Chat(name="New name"))
await chat.delete()

DDL — автоматическое создание таблиц

При первом запуске DotORM автоматически создаёт таблицы:

# Вызывается один раз при старте
async with ContainerTransaction(pool) as session:
    for model in all_models:
        foreign_keys = await model.__create_table__(session)

Генерируемый SQL:

CREATE TABLE IF NOT EXISTS chat_messages (
    id SERIAL PRIMARY KEY,
    chat_id INTEGER NOT NULL REFERENCES chats(id),
    author_user_id INTEGER NOT NULL REFERENCES users(id),
    body TEXT,
    is_edited BOOLEAN DEFAULT false,
    is_deleted BOOLEAN DEFAULT false,
    pinned BOOLEAN DEFAULT false,
    is_read BOOLEAN DEFAULT true,
    reply_to_id INTEGER REFERENCES chat_messages(id)
);