Skip to main content

djadmin

A clean, modern UI for the Django admin — plus the things the admin never shipped: a dashboard with real numbers, a command palette, and two-factor authentication.

djadmin does not reimplement the admin. It layers a new interface on top of django.contrib.admin, so everything you already know keeps working: list_display, list_filter, search_fields, actions, inlines, permissions, autocomplete, history, popups, filter_horizontal, date hierarchies.

What you get

The shell

  • Sidebar navigation grouped by app, with per-model icons, that collapses to an icon rail ([), or fully closes if you prefer (SIDEBAR_TOGGLE).
  • Command palette (⌘K / Ctrl+K) that searches models and records.
  • Light / dark / system theme, applied before first paint — no flash.
  • Keyboard shortcuts (/ search, c add, f filters, ⌘S save, ? help).
  • Messages as toasts, sticky save bar, mobile layout, RTL styles.
  • Delete confirmations in a dialog — fetched from Django's own confirmation view, so permissions, protected relations and the deletion tree are still computed server-side (and it degrades to the full page without JS).

The dashboard

  • Stat cards per model with a 14-day sparkline and a week-over-week delta.
  • Admin activity chart for the last 30 days, server-rendered as inline SVG (no chart library, no CDN, works with JavaScript disabled).
  • Recent-actions timeline.

The changelist

  • Sticky-header tables, filter panel that remembers its state, removable filter chips, a floating bulk-action bar that appears on selection, badges, progress cells and identity cells for list_display.

Authentication

  • TOTP two-factor authentication (RFC 6238, implemented on the standard library — works with 1Password, Google Authenticator, Aegis…).
  • Single-use recovery codes, stored as keyed hashes.
  • Replay protection, attempt throttling with lockout, expiring challenges.
  • A per-account Security page, and an optional org-wide MFA requirement.
  • Styled password change and password reset flows.

Install

pip install django-djadmin        # or: uv add django-djadmin
pip install "django-djadmin[mfa]" # adds QR codes on the MFA setup page
# settings.py
INSTALLED_APPS = [
    "djadmin",                          # before the admin app: template overrides
    "djadmin.apps.DjadminAdminConfig",  # replaces "django.contrib.admin"
    ...
]

That is the whole installation. Run manage.py migrate (djadmin adds two small tables for MFA) and open /admin/.

Configure

Everything is optional:

DJADMIN = {
    "BRAND": "Northwind",
    "ACCENT": "#5b5bd6",
    "THEME": "auto",              # auto | light | dark
    "SIDEBAR": "expanded",        # expanded | mini | hidden (initial state)
    "SIDEBAR_TOGGLE": "mini",     # what the button collapses to: mini | hidden
    "NAV_ACCORDION": False,       # one app group open at a time
    "DENSITY": "comfortable",     # comfortable | compact
    "APP_ICONS": {"shop": "cart"},
    "MODEL_ICONS": {"shop.order": "cart"},
    "HIDE_APPS": [],
    "DASHBOARD_STATS": True,
    "DASHBOARD_ANALYTICS": True,
    "ANALYTICS_DAYS": 30,
    "COMMAND_PALETTE": True,
    "MFA": {
        "ENABLED": True,
        "REQUIRED": False,        # False | True | "staff" | "superusers"
        "ISSUER": "Northwind admin",
        "CHALLENGE_TIMEOUT": 300,
        "MAX_ATTEMPTS": 5,
        "LOCKOUT_SECONDS": 300,
        "RECOVERY_CODES": 10,
    },
}

Use it in admin.py

Plain admin.ModelAdmin renders fine. djadmin.ModelAdmin adds a few declarations the UI understands:

from django.contrib import admin
import djadmin
from djadmin import avatar, badge, money, progress

@admin.register(Product)
class ProductAdmin(djadmin.ModelAdmin):
    icon = "box"                  # sidebar / dashboard / palette icon
    dashboard_order = 10          # position among the stat cards
    help_text = "Everything you sell."
    list_display = ("name", "status_badge", "price_display", "stock_display")

    @admin.display(description="Status", ordering="status")
    def status_badge(self, obj):
        return badge(obj.get_status_display(), "success", dot=True)

    @admin.display(description="Price", ordering="price")
    def price_display(self, obj):
        return money(obj.price)

Cell helpers: badge(text, tone, dot=False), money(amount, currency), progress(value, total, tone, label), avatar(name, subtitle, image_url). Tones: neutral, success, warning, danger, info, accent.

djadmin.TabularInline and djadmin.StackedInline mirror the Django ones.

The demo

A complete shop admin — products, orders with inlines, customers, reviews, tags with filter_horizontal, custom filters, bulk actions and seeded data.

uv sync                                   # or: pip install -e ".[demo]"
uv run demo/manage.py migrate
uv run demo/manage.py seed_demo           # ~20 products, 45 customers, 240 orders
uv run demo/manage.py runserver

Then open http://127.0.0.1:8000/admin/ and sign in with admin / admin.

Run the test suite (50 tests: every admin screen, the palette, the dashboard and the whole MFA flow):

uv run demo/manage.py test shop

Roadmap

docs/analytics-design.md is a full design for a website-analytics module — visitors, sessions, page views, sources, devices, countries, rollups, an opt-in tracking app and a dashboard. It was built and then parked; the design document stands on its own if it is picked up again.

The dashboard's own charts (per-model sparklines and the admin-activity graph) are unrelated to that and remain part of djadmin — see djadmin/charts.py.

Documentation

Full docs live in docs/ — installation, configuration, ModelAdmin, authentication and customising. Build them locally with uv run --with mkdocs-material mkdocs serve.

Compatibility

Python 3.10 – 3.14
Django 5.2 LTS, 6.0, 6.1

Every combination is exercised in CI. Django 4.2 is not supported: it reached end of life in April 2026 and lacks the collapsible-fieldset markup the forms rely on.

No runtime dependencies beyond Django; segno is optional and only used to draw the two-factor QR code.

License

MIT

Metadata

Release files for django-djadmin 0.1.0

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-djadmin 0.1.0
File Size Uploaded Provenance Actions
django_djadmin-0.1.0.tar.gz 103.1 kB With provenance Details for django_djadmin-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-djadmin 0.1.0
File Interpreter ABI Platform Actions
django_djadmin-0.1.0-py3-none-any.whl Python 3 none any Details for django_djadmin-0.1.0-py3-none-any.whl

Total release size: 202.6 kB

Release files / django_djadmin-0.1.0.tar.gz

Download URL django_djadmin-0.1.0.tar.gz
Size 103.1 kB
Tags Source
SHA-256 checksum
How to use checksums
17163779c57cae151dc0377ea28fcef176de37b8e79f12c82abef6d6c1ebf55f
BLAKE2b-256 checksum
How to use checksums
a41278633c25a279bdc8e320cb3396bc8b0e09b812e3be72f4e5e5de37233692
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 Aug 24, 2026.

Transparency log

Release files / django_djadmin-0.1.0-py3-none-any.whl

Download URL django_djadmin-0.1.0-py3-none-any.whl
Size 99.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
51dc4f7eaf47def3b564753398fbf19939663ad70d69cb16fc113bc29cd584bc
BLAKE2b-256 checksum
How to use checksums
5c0f6f54542c8704a7ffc9a6364e522424559397241df5b444ccd5da69536172
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 Aug 24, 2026.

Transparency log

Security for django-djadmin 0.1.0

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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for django_djadmin-0.1.0.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 Aug 24, 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

0.1.0 This release

2 release files Full provenance

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