djadmin
A clean, modern UI for the Django admin — plus the things the admin never shipped: a dashboard with real numbers, a command palette, a date picker that fits on one row, change history beside the form, 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,cadd,ffilters,⌘Ssave,?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. - Date filters are shortcut chips (Today, Last 7 days, This month…) plus a real from/to range, instead of Django's five fixed links.
Forms
- One picker for dates and times, in place of Django's calendar popups: a
DateFieldopens a month calendar, aDateTimeFieldopens that calendar next to a column of times. A datetime costs one row rather than the two rows, four shortcut controls and timezone paragraph the admin renders. - An object's change history sits in a rail beside the form, filling the column a change form otherwise leaves empty.
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.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django_djadmin-0.2.0.tar.gz | 120.1 kB | With provenance | Details for django_djadmin-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_djadmin-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for django_djadmin-0.2.0-py3-none-any.whl |
Total release size: 236.2 kB
Release files / django_djadmin-0.2.0.tar.gz
| Download URL | django_djadmin-0.2.0.tar.gz |
|---|---|
| Size | 120.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8f60e0da1d36c22f2586dacd5b9516cc25a876c896649356750c2306ac273d7d
|
|
BLAKE2b-256 checksum How to use checksums |
c464752dce6fedd9d92c8a4354e2421345691b304181d1dda25e6eaf3a8f93cc
|
| 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 25, 2026.
Transparency logRelease files / django_djadmin-0.2.0-py3-none-any.whl
| Download URL | django_djadmin-0.2.0-py3-none-any.whl |
|---|---|
| Size | 116.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d6f5e90bf98eeffcd2028e2fc10388617e1383cc765dd0903b2016a2309f15de
|
|
BLAKE2b-256 checksum How to use checksums |
a3bcddde1d79d89536fc2b595a96b2b75a554522065a2bd3936eb87a3d84cbba
|
| 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 25, 2026.
Transparency logSecurity for django-djadmin 0.2.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.
Attestation for django_djadmin-0.2.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 25, 2026.
Transparency logA 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.