Skip to main content

django-adminflow

A modern Django Admin UI template with built-in integrations for popular 3rd party packages.

PyPI version Python versions Django version License: MIT Docs

AdminFlow is a drop-in Django Admin UI template that replaces the default Django admin with a clean, minimalist SaaS-grade interface. Beyond the UI refresh, it ships with ready-to-use integrations for the most popular Django ecosystem packages — two-factor authentication, per-record audit history, and multi-format import/export — so you get powerful admin features with zero boilerplate.

One package. Install it, add it to INSTALLED_APPS, and your admin instantly looks and works like a premium SaaS product.


What is AdminFlow?

The default Django admin is functional but dated. AdminFlow wraps it with:

  • A modern, minimalist UI built with Tailwind utility classes and Material Symbols icons
  • A collapsible sidebar with app grouping, icons per model, and active state tracking
  • Responsive layouts — works on tablet and desktop
  • Clean typography using Inter font (loaded from Google Fonts)
  • Integrated 3rd party packages — install the extras you need, and the UI for them is already there

AdminFlow is not a full CMS replacement. It is a UI skin + integration layer for the Django admin you already use.


Screenshots

Login Dashboard
Login Dashboard
Customer List Change Form
Changelist Change form
Export Page Audit History
Export History
Import Page 2FA / User Security
Import 2FA

Features

Feature Description
🎨 Modern UI Minimalist SaaS design — sidebar navigation, clean typography, responsive layout
🔒 Two-Factor Auth TOTP (Google/Authy), email OTP, backup codes — multi-device support
📜 Audit History Per-record change history with field-level diffs
📤 Import / Export Multi-sheet XLSX + nested JSON with related models in one file
🔌 Plug & Play Add to INSTALLED_APPS — no extra config required for core UI
🌐 i18n Ready All UI strings use {% translate %}

Installation

# Core UI only
pip install django-adminflow

# With 2FA (django-otp)
pip install "django-adminflow[otp]"

# With audit history (django-simple-history)
pip install "django-adminflow[history]"

# With import / export (django-import-export)
pip install "django-adminflow[import-export]"

# Everything
pip install "django-adminflow[all]"

Setup — settings.py

INSTALLED_APPS

⚠️ "adminflow" must come before "django.contrib.admin"

INSTALLED_APPS = [
    "adminflow",                              # ← FIRST, before django.contrib.admin
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",

    # Add only what you installed:
    "simple_history",                         # audit history
    "import_export",                          # import / export
    "django_otp",                             # 2FA core
    "django_otp.plugins.otp_totp",            # TOTP (Google Authenticator, Authy)
    "django_otp.plugins.otp_email",           # email one-time passwords
    "django_otp.plugins.otp_static",          # backup / recovery codes
]

MIDDLEWARE

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django_otp.middleware.OTPMiddleware",                      # ← 2FA (after Auth)
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "simple_history.middleware.HistoryRequestMiddleware",        # ← history
]

TEMPLATES — context processor (required)

⚠️ Without adminflow.context_processors.adminflow_settings, the sidebar title, colours and login panel will not render.

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
                "adminflow.context_processors.adminflow_settings",  # ← required
            ],
        },
    },
]

urls.py — 2FA Verification Route

If using 2FA (django-otp), add adminflow_verify_2fa_view to urls.py before admin.site.urls:

from django.contrib import admin
from django.urls import path
from adminflow.views import adminflow_verify_2fa_view

urlpatterns = [
    path('admin/verify-2fa/', adminflow_verify_2fa_view, name='adminflow_verify_2fa'),
    path('admin/', admin.site.urls),
]

AdminFlow Settings

# ── Branding ──────────────────────────────────────────────────────────────────
ADMINFLOW_TITLE   = "My App"          # sidebar header + browser tab title
ADMINFLOW_COMPANY = "My Company"      # admin footer text
# ADMINFLOW_LOGO  = "logo.svg"        # path relative to MEDIA_URL (optional)

# ── Login page hero ───────────────────────────────────────────────────────────
ADMINFLOW_LOGIN_TITLE    = "Welcome back"
ADMINFLOW_LOGIN_SUBTITLE = "Sign in to manage your application."

# ── Theme colours ─────────────────────────────────────────────────────────────
ADMINFLOW_PRIMARY_COLOR             = "#1f2021"
ADMINFLOW_SECONDARY_COLOR           = "#475569"
ADMINFLOW_SUCCESS_COLOR             = "#10B981"
ADMINFLOW_WARNING_COLOR             = "#F59E0B"
ADMINFLOW_DANGER_COLOR              = "#EF4444"

# ── Sidebar ───────────────────────────────────────────────────────────────────
ADMINFLOW_SIDEBAR_COLOR             = "#0f172a"   # background
ADMINFLOW_SIDEBAR_TEXT_COLOR        = "#94a3b8"   # inactive item text
ADMINFLOW_SIDEBAR_ACTIVE_TEXT_COLOR = "#ffffff"   # active item text
ADMINFLOW_SIDEBAR_COLLAPSIBLE       = True
ADMINFLOW_SIDEBAR_WIDTH             = 280         # pixels

# ── UI ────────────────────────────────────────────────────────────────────────
ADMINFLOW_BORDER_RADIUS             = "16px"
ADMINFLOW_FONT                      = "Inter"     # any Google Font name
ADMINFLOW_ENABLE_COMMAND_PALETTE    = True        # Cmd+K quick search

# ── 2FA ───────────────────────────────────────────────────────────────────────
ADMINFLOW_DJANGO_OTP = True    # show OTP verification screen after login

Email (for Email OTP)

EMAIL_BACKEND               = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST                  = "smtp.gmail.com"
EMAIL_PORT                  = 587
EMAIL_USE_TLS               = True
EMAIL_HOST_USER             = "noreply@myapp.com"
EMAIL_HOST_PASSWORD         = "your-smtp-password"    # use .env, never commit
DEFAULT_FROM_EMAIL          = EMAIL_HOST_USER

OTP_EMAIL_SENDER            = EMAIL_HOST_USER
OTP_EMAIL_FROM_EMAIL        = EMAIL_HOST_USER
OTP_EMAIL_COOLDOWN_DURATION = 60    # seconds between OTP requests

3rd Party Integrations

🔒 Two-Factor Authentication — django-otp

# admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from adminflow.user_admin import AdminFlowUserAdminMixin, get_2fa_inlines, unregister_otp_models

User = get_user_model()

@admin.register(User)
class UserAdmin(AdminFlowUserAdminMixin, BaseUserAdmin):
    inlines = get_2fa_inlines()

unregister_otp_models()   # removes raw django-otp admin entries

What you get: TOTP + email OTP + backup codes, multi-device per user, admin bulk actions (Enable 2FA, Generate backup codes).


📜 Audit History — django-simple-history

# models.py
from simple_history.models import HistoricalRecords

class Customer(models.Model):
    name  = models.CharField(max_length=200)
    email = models.EmailField(unique=True)
    history = HistoricalRecords()   # ← add this

# admin.py
from simple_history.admin import SimpleHistoryAdmin

@admin.register(Customer)
class CustomerAdmin(SimpleHistoryAdmin):
    list_display = ('name', 'email')

📤 Import / Export — django-import-export

Add import_export to INSTALLED_APPS, then use MultiSheetExportImportMixin:

# resources.py
from import_export import resources, fields
from import_export.widgets import ForeignKeyWidget
from .models import Customer, Order

class CustomerResource(resources.ModelResource):
    class Meta:
        model  = Customer
        fields = ('id', 'name', 'email', 'phone', 'notes', 'date_created')

class OrderResource(resources.ModelResource):
    customer = fields.Field(
        column_name='customer_email',
        attribute='customer',
        widget=ForeignKeyWidget(Customer, field='email'),
    )
    class Meta:
        model  = Order
        fields = ('id', 'customer', 'product', 'order_date', 'status', 'total_amount')

# admin.py
from adminflow.import_export import MultiSheetExportImportMixin
from import_export.admin import ImportExportModelAdmin

@admin.register(Customer)
class CustomerAdmin(MultiSheetExportImportMixin, ImportExportModelAdmin, admin.ModelAdmin):
    combined_sheets = [
        ('General Details', CustomerResource, None),
        ('Orders', OrderResource, lambda qs: Order.objects.filter(customer__in=qs)),
    ]

Export formats:

Format Output
xlsx One .xlsx file — one sheet per resource
json One .json file — children nested inside each parent record

JSON output example:

[
  {
    "id": "1",
    "name": "Alice Johnson",
    "email": "alice@example.com",
    "orders": [
      { "id": "1", "customer_email": "alice@example.com", "order_date": "2026-07-22", "status": "delivered" }
    ]
  }
]

Customisation

# admin.py — Material Symbols icon per model
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    icon = "inventory_2"   # browse at fonts.google.com/icons

# apps.py — sidebar group label
class CrmConfig(AppConfig):
    name         = "crm"
    verbose_name = "Customer Relations (CRM)"

Changelog

v1.0.0 — 2026-07-23

  • Initial stable release
  • Modern minimalist admin UI (sidebar, Inter font, responsive)
  • Full 2FA: TOTP, email OTP, backup codes, multi-device
  • Audit history with field-level diffs (django-simple-history)
  • Multi-sheet XLSX export/import (one sheet per related model)
  • Nested JSON export (children embedded inside parent records)
  • MultiSheetExportImportMixin for plug-and-play multi-resource export
  • Styled Import / Export buttons, export page with field chips, import page
  • All ADMINFLOW_* theme settings

Documentation

Full documentation: django-adminflow.readthedocs.io/en/latest

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_adminflow-1.0.13.tar.gz (224.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_adminflow-1.0.13-py3-none-any.whl (238.3 kB view details)

Uploaded Python 3

File details

Details for the file django_adminflow-1.0.13.tar.gz.

File metadata

  • Download URL: django_adminflow-1.0.13.tar.gz
  • Upload date:
  • Size: 224.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for django_adminflow-1.0.13.tar.gz
Algorithm Hash digest
SHA256 d4cfc971443e8dcb5f78beec0bcb3093e2873c4aeecb413cbd32df5c535bf22b
MD5 c20ef27c0402a7a93844431ac351e468
BLAKE2b-256 47878112c7e946998cb7f75506b364e8208560fd4812d113cc0bf009ca0b515a

See more details on using hashes here.

File details

Details for the file django_adminflow-1.0.13-py3-none-any.whl.

File metadata

File hashes

Hashes for django_adminflow-1.0.13-py3-none-any.whl
Algorithm Hash digest
SHA256 b4afb59762a0845563c320eb8fb74a7dee0bf26ce2a2661bd653339f49a36ead
MD5 0f2b2c9f448689c6b103fa5b2d48bcbf
BLAKE2b-256 dfd418d40f467aec99687b5db84b3338e14b3c4cffadc125739abc90d37cb1ae

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page