LazyDjango is a keyboard-first TUI for Django projects inspired by LazyVim and LazyGit. It gives you one place to inspect project state, run common tasks, browse/edit model data, and manage snapshots.
- Django project auto-discovery (
manage.pyin current/parent directories) - LazyGit-style panel layout with clear focus and
>cursor selection - Active panel frame/title highlighting for clearer focus state
- Model browsing with pagination and CRUD modals
- Snapshot create/list/restore for SQLite/PostgreSQL/MySQL
- Docker-aware workflows (service selection + start/stop actions)
- Makefile-aware workflows (
make help+ curated task actions) - Startup update check against latest GitHub release (non-blocking)
- Startup summary in Output with quick-start guidance
- Project-scoped memory and history files under
.lazy-django/
brew tap William-Blackie/lazydjango https://github.com/William-Blackie/lazydjango
brew install --formula William-Blackie/lazydjango/lazy-django
brew upgrade --formula William-Blackie/lazydjango/lazy-djangoPrerequisites:
- Go
1.21+ - Python with Django for target projects
- Optional: Docker + Docker Compose
Build:
./build.shRun from inside a Django project (or any subdirectory of it):
/path/to/lazy-djangoDependency preflight:
/path/to/lazy-django --doctor --doctor-strict --project ./demo-project
/path/to/lazy-django --doctor --doctor-json --project ./demo-projectProject: status + workflow actionsDatabase: discovered modelsData: snapshot actionsOutput: command/log tabs and model record tables
Project panel actions are intentionally compact:
Server...(start/stop dev server)Containers...(if Docker configured)Project Tasks...(project-local task list)Favorites...(project command MRU)Recent Commands...(rerun command history)Migrations...Tools...(includesHistory report)
1/2/3/4: focusProject/Database/Data/OutputTab/Shift+Taborh/l: previous/next panelj/k: move selection (or scroll output when Output is focused)Enter: execute/open selected item:: open centered command modal (run shell/manage/make commands):help: open in-app keybindings/instructions modal/: open centered search modal and jump to closest match in focused panel/outputv: toggle output selection mode (Output panel)y: copy output line or selected output rangei: send input to the running process in selected output tabr: refresh project metadataU: open update detailsqorCtrl+C: quit
Enter: run action / open action modale: edit selected task configuration (when cursor is onProject Tasks...or inside that modal)u: start container selector modalD: stop container selector modal- in action modals:
0-9jumps to numbered action rows
Enter: open selected model in Output panel
j/korJ/K: next/previous recordn/p: next/previous pagea: add recorde: edit selected recordd: delete selected recordEsc: close model table view- in field picker modals:
/search options,nload more FK rows,xclear nullable value
- each command creates a new output tab
t: tab picker modal[/]: previous/next tabo: jump to latest tab of the other type (Command/Logs)x: close active tabCtrl+L: clear active tabv: start/stop line selection modej/k(while selecting): extend selectiony: copy current line or selected lines to clipboardi: open process input prompt (for interactive commands)
Enter: run selected snapshot actionc: create snapshotL: list snapshotsR: restore snapshot modal
LazyDjango stores project-local state in:
<project>/.lazy-django/state.json
State includes:
- focused panel and panel selections
- output tab state (bounded count and bounded text)
- command history
- favorite commands (MRU quick-run)
- recent model context (page/selection)
- deduplicated recent errors
Event history is appended to:
<project>/.lazy-django/history.ndjson
Events include command runs, container actions, snapshot actions, model opens, and errors. Retention is capped so files stay small.
Snapshot data is stored in:
<project>/.lazy-django/snapshots/
Project task memory is stored in:
<project>/.lazy-django/tasks.json
On first run, LazyDjango writes tasks from the discovered project workflow (make help + Django actions) for the project it was started in; after that, this file is the source of truth until you edit it.
This file is project-local and should stay out of version control in your app repo.
Primary workflow:
make build
make doctor
make test
make race
make vet
make smoke
make release-check
make release-snapshotDirect scripts:
./build.sh
./smoke-test.shQuality gates:
go test ./...
go test -race ./...
go vet ./...
go run ./cmd/lazy-django --doctor --doctor-strict --project ./demo-projectNo available formula with the name "lazydjango": install with full pathWilliam-Blackie/lazydjango/lazy-django.- Broken tap state or merge conflict in tap files during
brew update: reset the tap checkout:brew update-reset william-blackie/lazydjangoIf needed, re-tap cleanly:brew untap william-blackie/lazydjango && brew tap william-blackie/lazydjango https://github.com/William-Blackie/lazydjango Repository not foundduring tap: use explicit tap URL from install command and ensure repo access.- macOS quarantine warning: remove quarantine from the actual Homebrew target binary:
BREW_BIN="$(brew --prefix)/bin/lazy-django"; TARGET="$(readlink "$BREW_BIN" 2>/dev/null || echo "$BREW_BIN")"; xattr -dr com.apple.quarantine "$TARGET"
PRs are welcome. Keep changes scoped and include tests for behavior changes.
Tag-based releases run through .github/workflows/release.yml.
Use RELEASE_CHECKLIST.md before tagging.