django-anvil v0.1
🔍Search docs...⌘K
Guides

Demo project

demo/ in the repository is a full, runnable Django project proving every feature end to end — not a toy. Four Resources in one app:

The four demo Resources

ResourceDemonstrates
ProductRBAC (mixed public/codename rules), tenancy, SoftDeleteViewSetMixin, TimestampedSerializerMixin
CouponRBAC (all codenames, no public), tenancy, audit history
ReviewOwnerScopedViewSetMixin, the "authenticated" permission rule, deliberately not tenant-scoped
TagAdded live via anvil ai --apply during development — proof the AI engine's propose→approve→write loop produces a genuinely working Resource, not just a plausible-looking diff

Run it yourself

python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cd demo
python manage.py migrate
python -m pytest products/ -v      # 49 tests
python manage.py anvil doctor

seed_demo

Populates organizations, roles, users, and sample data — safe to re-run (everything is get_or_create'd):

python manage.py seed_demo
python manage.py runserver

Demo accounts

AccountWhat it can do
adminSuperuser — full Django admin access
aliceAcme Manager — sees only Acme's Products/Coupons/Tags, full CRUD
bobGlobex Manager — sees only Globex's, full CRUD
carolAcme Staff — view-only; create/update/delete all 403
daveNo organization — sees nothing (tenancy fails closed)

Password for all: demo-pass-1234. seed_demo prints this list itself, so you never need to remember it.

Try it

curl http://127.0.0.1:8000/api/products/
# [] -- anonymous, no organization context

curl -u alice:demo-pass-1234 http://127.0.0.1:8000/api/products/
# Acme's products only

curl -u carol:demo-pass-1234 -X POST http://127.0.0.1:8000/api/products/ \
  -d 'name=Test&price=1&stock=1&is_active=true'
# 403 -- Staff, view-only

Or open http://127.0.0.1:8000/admin/ to browse Roles, Organizations, Products, Coupons (with a "History" button from audit logging), Reviews, and Tags directly.

💡

Every one of these behaviors was verified against a live running server with real curl requests and a real browser session — not just pytest — while the demo was being built. Several real bugs (a crash on anonymous ownership-scoped requests, a script that fell into its own tenancy footgun, a missing integer field type) were caught exactly this way.