django-anvil v0.1
🔍Search docs...⌘K
Core concepts

Audit history & anvil doctor

Audit history

Wraps django-simple-history rather than reinventing change tracking. Set audited = True on a Resource:

class CouponResource(Resource):
    model = Coupon
    ...
    audited = True

and add the history field to the model yourself — Anvil never edits model files for you, the same policy as TenantScopedModel:

from simple_history.models import HistoricalRecords

class Coupon(TenantScopedModel):
    ...
    history = HistoricalRecords()

Anvil wires up the admin integration: the generated ModelAdmin uses SimpleHistoryAdmin instead of admin.ModelAdmin, giving a full "History" button and change log in the Django admin UI automatically.

django-simple-history is already installed as part of django-anvil — just add "simple_history" to INSTALLED_APPS.

💡

Verified for real: create a row, change it twice, instance.history.all() shows three entries — + (created), ~, ~ (two updates) — each with its own timestamp.

anvil doctor

Static checks, no database needed — safe to run in CI before migrate:

python manage.py anvil doctor
CheckLevel
DEBUG=TrueWarning
Unreplaced default SECRET_KEYWarning
ALLOWED_HOSTS empty with DEBUG=FalseError
A tenant_scoped Resource whose model isn't really TenantScopedModelError
A mixin used without the field it needs (SoftDeleteViewSetMixinis_deleted, OwnerScopedViewSetMixinowner)Error
A permission codename that doesn't match any real permission on the modelWarning
audited = True but the model has no history field yetWarning
A field filtered/sorted on a lot with no database indexInfo
⚠️

The permission-codename check exists specifically because RBAC fails closed: a typo'd codename doesn't raise an error anywhere — it just silently locks everyone out of that action forever, with nothing in the logs to point at the cause. This is the one check most worth running after any change to a Resource's permissions.

[WARN] security: DEBUG=True -- fine for local development, never deploy with this on.
[WARN] security: SECRET_KEY is still Django's auto-generated insecure default -- replace it before deploying.
[INFO] performance: ProductResource (products.Product): 'price' is filtered/sorted on but has no db_index -- consider adding one if the table gets large.

0 error(s), 2 warning(s), 1 suggestion(s)