Команда fastfort

Четыре команды — ключ подписи, первая учётная запись, отчёт о конфигурации, блокирующий деплой, и список того, чем управляет админка.

Доступно с версии v0.1.0

uv add "fastfort[cli]"

Четыре вещи нужны проекту, прежде чем админка вообще сможет запуститься: секретный ключ, первая учётная запись для входа, способ проверить, что конфигурация корректна, и способ увидеть, что зарегистрировано. Без первых двух свежая установка непригодна к использованию без написания отдельного скрипта.

--app

Каждая команда, обращающаяся к вашему проекту, принимает этот параметр:

uv run fastfort check --app main:fort

module:attribute — где живёт экземпляр FastFort. Он импортируем, потому что ваш main.py создаёт его на уровне модуля.

generate-secret

uv run fastfort generate-secret
uv run fastfort generate-secret --export     # FASTFORT_SECRET_KEY=…
uv run fastfort generate-secret --length 64

Только выводится на экран — и ничего больше. Никогда не записывается в файл. Секрет, который инструмент положил на диск, — это секрет, который рано или поздно попадёт в коммит.

В FastFortSettings нет значения secret_key по умолчанию, потому что фреймворк, поставляющий такое значение, гарантированно получит хотя бы один деплой, работающий именно с ним. Валидатор также отклоняет заполнитель-заглушку, всё короче 32 символов и всё, что использует менее 8 различных символов.

createsuperuser

# Interactive
uv run fastfort createsuperuser --app main:fort

# CI
FF_PASSWORD='…' uv run fastfort createsuperuser \
    --app main:fort \
    --identity you@example.com \
    --password-env FF_PASSWORD \
    --no-input

--password-env, а не --password: пароль, переданный аргументом, виден в истории командной строки и в ps. При интерактивной передаче --password выводится предупреждение об этом.

Команда проверяет пароль на соответствие auth.password_min_length и списку распространённых паролей, отклоняет дублирующийся идентификатор и записывает только те поля, которые спецификация помечает как редактируемые, — поэтому отсутствие в модели пользователя одного из пяти общепринятых столбцов не приводит к сбою: лишний ключ просто отбрасывается.

check

uv run fastfort check --app main:fort
uv run fastfort check --app main:fort --deploy

Собирает все проблемы вместо того, чтобы падать на первой же, и завершается с ненулевым кодом — благодаря этому команда может блокировать деплой:

Fastfort Freight · 17 model(s)
warn  debug=True exposes tracebacks and internal state. Set FASTFORT_DEBUG=false.
warn  security.cookie_secure=False sends the session cookie over plain HTTP.
      Set FASTFORT_SECURITY__COOKIE_SECURE=true and serve over HTTPS.
warn  auth.access_token_ttl is 7200s. A leaked access token stays valid that
      long; 900s is the recommended ceiling.

3 problem(s) found.

Без --deploy проверяется только монтаж: отсутствующий бэкенд, отсутствующая модель пользователя, модель, с которой бэкенд не может работать, пустой реестр. С этим флагом — ещё и проверки для продакшена.

- name: Configuration check
  run: uv run fastfort check --app main:fort --deploy
  env:
    FASTFORT_SECRET_KEY: ${{ secrets.FASTFORT_SECRET_KEY }}
    FASTFORT_DEBUG: "false"

registered-models

uv run fastfort registered-models --app main:fort
Accounts
  accounts.user                app.models.accounts.User
                               /admin/accounts.user/
  accounts.role                app.models.accounts.Role
                               /admin/accounts.role/

Catalog
  catalog.product              app.models.catalog.Product
                               /admin/catalog.product/

Показывает, чем управляет админка, где живёт каждая модель и URL каждой страницы. Полезно, когда нужно понять, нашёл ли autodiscover то, что вы ожидали.

version

uv run fastfort version

Регистрация — явная или через автообнаружение

fort.include_admin("app.admin")           # named; an import error names the module
fort.autodiscover("app")                  # walks for every app/**/admin.py

autodiscover возвращает то, что импортировал, а registered-models выводит этот результат — так что произошедшее всегда видно, а не остаётся магией. Модули, вызывающие исключение при импорте, не подавляются.