Архитектура
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; новые возможности подключаются явно.
Путь изменения записи
- Проверить подписанную сессию и актуальность пользователя в backend авторизации.
- Проверить право на операцию с таблицей.
- Ограничить тело запроса, разобрать форму, отклонить дубликаты и проверить CSRF.
- Сформировать серверный allowlist полей и отклонить неизвестные, скрытые и read-only поля.
- Преобразовать строки в скалярные типы и вернуть ошибки в форму.
- Проверить подписанную ревизию формы. Вызвать before-write hook и выполнить операцию
адаптера в своей транзакции, атомарно проверяя актуальность записи и редактируемых связей. - При конфликте откатить транзакцию и вернуть
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-окружения описаны в матрице совместимости.