Архитектура

FastAPI mount ───┐
                ├── Admin ASGI / Starlette ── Jinja2 UI / интерактивные компоненты
Litestar mount ─┘              │
                    Авторизация / CSRF / права
                              │
                    ModelSchema / Field / Query
                              │
                       Контракт Adapter
                              │
               SQL Core / SQLAlchemy / Tortoise / Peewee / GINO / сервисы

Два режима доступа к данным

Общего API introspection/persistence у Python ORM нет. SQL reflection обнаруживает
физические таблицы независимо от ORM приложения. Но в БД нет информации о Python defaults,
Enum-классах, model validators и правилах сервисов. Reflection и ORM-адаптеры —
разные явные варианты подключения.

SQLAdapter использует SQLAlchemy как SQL toolkit. SQLAlchemyAdapter использует
ORM-сессии и ORM persistence. Для soft delete, изоляции арендаторов и прикладных
инвариантов реализуйте адаптер над сервисом приложения.

Контракты

  • ModelSchema: имя таблицы, скалярные поля, один или несколько первичных ключей.
  • Field: тип, nullable/default/generated/read-only, варианты значений и метаданные FK.
  • ModelOptions: независимая от ORM политика отображения и записи.
  • Query: проверенные пагинация, сортировка, текстовый поиск, типизированные фильтры и проекции.
  • RelatedFilter: условие связи с целевой записью по типизированному ключу; поддержка адаптером необязательна.
  • Relation, Junction: метаданные связей и промежуточных таблиц для редакторов и схемы БД.
  • CheckedAdapter, WriteGuard: необязательная атомарная проверка актуальности редактируемой записи.
  • RecordPage: словари скалярных значений и общее количество.
  • Adapter: обнаружение, описание схемы и пять CRUD-операций.
  • AuthBackend: проверка учётных данных и повторная проверка пользователя.

Дескриптор модели может быть ORM-классом, SQL-таблицей или дескриптором внешнего repository.
Ядро не импортирует ORM; неиспользуемые адаптеры не добавляют требований установки.
Версия обязательного API адаптера остаётся 1; новые возможности подключаются явно.

Путь изменения записи

  1. Проверить подписанную сессию и актуальность пользователя в backend авторизации.
  2. Проверить право на операцию с таблицей.
  3. Ограничить тело запроса, разобрать форму, отклонить дубликаты и проверить CSRF.
  4. Сформировать серверный allowlist полей и отклонить неизвестные, скрытые и read-only поля.
  5. Преобразовать строки в скалярные типы и вернуть ошибки в форму.
  6. Проверить подписанную ревизию формы. Вызвать before-write hook и выполнить операцию
    адаптера в своей транзакции, атомарно проверяя актуальность записи и редактируемых связей.
  7. При конфликте откатить транзакцию и вернуть 409. После commit вызвать after-write hook
    и перенаправить. При устаревшей форме введённые значения сохраняются.
    См. операции и расширения и конкурирующее редактирование.

В сессии хранится subject. Роли и актуальность пользователя поступают из backend
при каждом защищённом запросе. Ключи записей — URL-safe base64 JSON-массивы,
декодируемые в типизированные значения. Поддержаны UUID, составные ключи и строки
со слешами. Кодирование не заменяет проверку прав.

Асинхронность и жизненный цикл

Синхронные SQLAlchemy/Peewee операции целиком выполняются в anyio.to_thread.run_sync.
Сессия и connection создаются и закрываются в том же потоке.
SQLAlchemy AsyncSession.run_sync связывает ORM-операции с асинхронным DB I/O.
Tortoise и GINO используют родные асинхронные API. GINO 1.x работает в отдельном
окружении SQLAlchemy 1.3; его не устанавливают вместе с адаптерами SQLAlchemy 2.x.

Приложение владеет engine/pool, миграциями и startup/shutdown. Обнаружение моделей
происходит после startup, что существенно для Tortoise raw FK. Reflection кеширует
метаданные и атомарно заменяет их при refresh(). Главная не выполняет COUNT(*)
для каждой таблицы: запросы записей начинаются при открытии списка.

Интерактивные экраны

Фильтры списков строят проверенный Query; адаптер применяет условия
до подсчёта и пагинации. Выбор связей загружает по 25 вариантов с повторной проверкой
прав на каждый запрос. Схема БД читает только метаданные доступных
таблиц и полей; значения записей в граф не попадают.

HTML рендерится на сервере. Встроенные фильтры, выбор связей и схема используют
локальные скрипты с SRI и точными CSP-хешами на соответствующих страницах.
Свои страницы после входа получают общие скрипты навигации; произвольные скрипты
страницы по-прежнему запрещены.

Рендеринг и браузерное демо используют общие построитель метаданных навигации,
реестр встроенных ресурсов и шаблоны навигации. Проверка прав выполняется заново
для каждого запроса перед построением каталога. Кешируются только хеши встроенных
скриптов: метаданные файла сбрасывают ограниченный кеш при изменении или замене,
сохраняя соответствие SRI/CSP. Демо клонирует разобранную оболочку для каждого языка
и использует настоящий partial кнопки избранного.

Скрипт навигации по таблицам владеет разрешённым каталогом и состоянием браузера;
главная использует этот API вместо отдельного хранилища. Неизменившаяся строка
хранилища разбирается один раз, а неизменившиеся наборы карточек сохраняют DOM
и фокус клавиатуры. Ключи хранилища, контекст шаблонов и CSS-селекторы совместимы
с прежними версиями. Общая разметка полосы значков вынесена в отдельный partial,
чтобы старые переопределения _ui.html продолжали работать.

Точки расширения

  • Доступ к данным: Adapter.
  • Пользователь и роли: AuthBackend.
  • Таблицы и поля: ModelOptions, FieldOptions, register(), configure().
  • Оформление и формы: переопределение Jinja-шаблонов в своём каталоге.
  • Дополнительные экраны: Page, context callback и permission.

Права применяются к таблице целиком; фильтрация строк относится к адаптеру.
GET не изменяет записи. Удаление требует POST после страницы подтверждения.

Интеграция с фреймворками

FastAPI использует ASGI sub-application mounting,
Litestar — ASGI mount handlers.
Обёртка приводит относительные нормализованные пути Litestar к Starlette path/root_path.
Тесты проверяют вложенные роутеры и reverse-proxy prefixes.

SQLAlchemy предоставляет runtime inspection
и MetaData reflection.
Tortoise предоставляет метаданные моделей,
Peewee — Model._meta.
Проверки PostgreSQL/MySQL и отдельного GINO-окружения описаны в матрице совместимости.