Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

django-vantage

A smart, beautiful admin panel for Django.
Zero config to start. One line to override anything.

PyPI Python Django CI Licence: MIT

Documentation · Getting started · Changelog · FAQ

The Orders list in django-vantage: stat cards with trends, a revenue chart, a status breakdown, filters and a data grid

Alpha (0.1.0a1). Working and heavily tested — more than 3,600 tests — but the API may still move. See the FAQ for an honest account of what is and is not done. Use it on an internal tool, and pin the exact version if you depend on it.

Why

Django's built-in admin is remarkable for what it is, and it hasn't fundamentally changed in twenty years. django-vantage keeps what made it great — configuration in ordinary Python, next to your models — and rebuilds everything else: the rendering, the data grid, the relationship handling, and the look.

Two rules govern the whole package:

  1. Smart. Install it, and every model in your project already has a good admin — columns, filters, search, widgets, and query optimisation inferred automatically.
  2. Easy. Every inferred default is overridable in one line. If it takes more, the API is wrong.

Install

pip install --pre django-vantage

--pre is needed while Vantage is in alpha, because pip skips pre-releases unless asked.

# settings.py
INSTALLED_APPS = ["vantage", ...]

# urls.py
from django.urls import path
from vantage import site

urlpatterns = [path("admin/", site.urls)]

That is the entire setup. Every model is now administrable, with a dashboard, a searchable data grid, create/edit/delete, a command palette, light and dark themes, and a schema map.

Customise a model

Create panel.py next to your models.py:

from vantage import ModelPanel, register
from blog.models import Post

@register(Post)
class PostPanel(ModelPanel):
    list_display = ["title", "author", "status", "published_at"]

Overriding list_display overrides only the columns. Filters, search fields and widgets stay inferred. Partial configuration never opts you out of the intelligence.

Not sure what it inferred? Ask it to write it down:

python manage.py vantage_scaffold blog

That prints a real panel.py containing exactly what Vantage decided, which you can then own and edit. Delete an attribute and it goes back to being inferred.

Statistics and charts on any list page

Declared in Python, computed against the currently filtered queryset, no JavaScript:

from vantage import Chart, ModelPanel, Stat, register
from django.db.models import Avg, Count, Q, Sum

@register(Order)
class OrderPanel(ModelPanel):
    list_filter = ["status", "created_at"]

    list_stats = [
        Stat("Revenue",   Sum("total"), format="currency", trend="created_at"),
        Stat("Orders",    Count("id")),
        Stat("Avg order", Avg("total"), format="currency"),
        Stat("Refunded",  Count("id", filter=Q(status="refunded")), tone="destructive"),
    ]
    list_charts = [
        Chart.timeseries("Revenue over time", date="created_at", value=Sum("total")),
        Chart.breakdown("By status", group_by="status", value=Count("id"), kind="donut"),
    ]

Change a filter and every number follows. Filter to the last 90 days and Revenue compares itself with the 90 days before. All four stats fold into one shared aggregate() call, plus one more for the trend window — two queries total, however many non-trending stats you add. The charts render as inline SVG that follows your brand colour and the current theme.

There is also a per-column summary bar at the foot of every table, which needs no configuration at all — a money column is summed, a rating column is averaged, and an identifier is left alone.

Dashboard with stat cards, a revenue chart and the latest orders and reviews

Dashboard — widgets declared in Python or arranged from the UI

The command palette searching for orders

Command palette — ⌘ K to go anywhere

An inferred edit form, grouped into sections

Forms — inferred widgets and sections, or your own layout

The schema map showing models and their relations

Schema map — derived from the registry, never out of date

Bulk actions

Ordinary methods with a decorator:

from vantage import ModelPanel, action, register

@register(Review)
class ReviewPanel(ModelPanel):
    @action("Publish", icon="check")
    def publish(self, request, queryset):
        return f"Published {queryset.update(is_published=True)} reviews."

    @action("Delete", destructive=True, permission="delete", max_rows=500,
            confirm="Permanently delete {count} reviews?")
    def delete_selected(self, request, queryset):
        deleted, _ = queryset.delete()
        return f"Deleted {deleted} records."

"Select all matching" travels as a predicate plus an exclusion set, never as a list of ids, so selecting forty thousand rows costs the same as selecting three. The scope actually resolved is always reported back — a bulk action must never quietly apply to less than you asked for.

Lay out a form

from vantage import Row, Section, Tab, Tabs

layout = Tabs(
    Tab("Content", Section(Row("title", "slug"), "body")),
    Tab("SEO", Section("meta_title", "meta_description")),
)

A field the layout forgets is appended rather than dropped, and a field it names that does not exist fails manage.py check rather than silently vanishing from the form.

Brand it

VANTAGE = {
    "SITE_TITLE":  "Acme",
    "LOGO":        "img/acme.svg",
    "BRAND_COLOR": "#0ea5e9",
    "THEME":       "system",
}

One colour produces a complete palette for both themes, with contrast checked: the derived primary and its foreground are guaranteed to clear WCAG AA for any hue you supply.

Anything here can also be edited in the panel by a superuser — logo upload, brand colour, title, theme — and the database value overrides the file.

Organise the sidebar

VANTAGE = {
    "NAV": [
        {"route": "vantage:dashboard", "label": "Overview", "icon": "layout-dashboard"},
        {"group": "Commerce", "items": [
            {"model": "shop.Order", "badge": "live"},
            {"model": "shop.Product", "label": "Catalogue"},
        ]},
        {"group": "Elsewhere", "items": [
            {"url": "https://status.example.com", "label": "Status"},
        ]},
    ],
}

Declaring a nav can reorder, rename and hide — it can never grant access. Every entry still passes through the permission layer.

Add your own page

from vantage import Page, site

@site.register_page
class RevenuePage(Page):
    title = "Revenue"
    icon  = "trending-up"

    def get_context(self, request):
        return {"total": Order.objects.total_revenue()}

A class, a title, and a method. The URL, the nav entry and the rendering all have defaults, so a page with no template of its own still produces a presentable screen.

Configure it from the UI too

Everything above is the developer's API. The person running the panel day to day can often reach the same knobs without a deploy: a list's columns, filters, stats and charts have a customisation rail, the dashboard has its own "Add a card" editor, and branding and behaviour have a settings screen. All of it composes in one fixed order — UI override → panel.py / VANTAGE → inference — stated once in How configuration resolves, so "why is my panel.py being ignored?" has a single, findable answer.

What else is in the box

JSON API Every panel, through the same permission and validation path as the UI — cursor pagination, optimistic concurrency, errors as structured data. Docs →
Command palette ⌘ K with global search across every model you can see
Dashboard Widgets declared in Python, or built and arranged from the UI — stat, chart, table, list, or your own template
Soft delete A real Trash tab and Restore on any model with a deleted_at or is_deleted column, detected automatically
Duplicate and bulk edit Both reuse the exact form and validation a single record uses
Multi-tenancy Scope every registered model to a tenant with one setting, fail-closed. Docs →
Cascade-delete preview The real tree of what a delete takes with it, counted
Read-only mode, impersonation Both enforced in the permission layer
System health page Migrations, cache, database, task backend
Streaming CSV export, CSV import Export honours the filters and sort you are looking at; import maps, previews and validates first
Light, dark and system themes, RTL All from day one, with en and ar catalogues shipped
Query-count guarantees select_related and prefetch_related are derived from what the page renders, and tests assert the cost does not grow with the row count

Requirements

Python 3.12, 3.13, 3.14 · Django 5.2 LTS, 6.0, 6.1

Django is the only runtime dependency. No Node.js — assets ship prebuilt. django-guardian, django-rules and django-simple-history are used if present, never required.

Try the demo

A full demo shop lives in example/:

git clone https://github.com/Pythondeveloper6/django-vantage
cd django-vantage
uv sync --all-groups
./example/run.sh          # migrate, seed, and serve on :8765

Sign in as admin / admin12345.

Contributing

Contributions are welcome — bug reports, docs fixes and pull requests alike. Start with CONTRIBUTING.md, and please report security issues privately as described in SECURITY.md.

uv sync --all-groups
uv run pytest
uv run ruff check src tests
uv run mkdocs serve       # the documentation site, on :8000

Licence

django-vantage is open source under the MIT licence. Copyright © 2026 Mahmoud Ahmed.

You may use, modify and redistribute it, commercially or not, as long as the copyright notice and the licence text are kept in every copy or substantial portion of the code. If django-vantage helps your project, a link back to this repository is always appreciated.

Metadata

Release files for django-vantage 0.1.0a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-vantage 0.1.0a1
File Size Uploaded Provenance
django_vantage-0.1.0a1.tar.gz 1.1 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-vantage 0.1.0a1
File Interpreter ABI Platform
django_vantage-0.1.0a1-py3-none-any.whl Python 3 none any Details

Total release size: 1.9 MB

Release files / django_vantage-0.1.0a1.tar.gz

Download URL django_vantage-0.1.0a1.tar.gz
Size 1.1 MB
Tags Source
SHA-256 checksum
How to use checksums
30252aade27b506e5b9c56b5a80722d2b36058d4ab87d70b821bc4c51bd0efaf
BLAKE2b-256 checksum
How to use checksums
933695d344b996d42f96487338188ac6fc57b2e608caa82a0f6e73bc71262c86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Release files / django_vantage-0.1.0a1-py3-none-any.whl

Download URL django_vantage-0.1.0a1-py3-none-any.whl
Size 794.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4214b1deb4f9c59fa42e0a0db7ec11db0be89b5af761e21540df02566eb63267
BLAKE2b-256 checksum
How to use checksums
5fe6ea731eb6c737dd6d82117d96cbfe123905ac1e5901d7dc2b8417cbaf2efb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Security for django-vantage 0.1.0a1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for django_vantage-0.1.0a1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page