Metadata-Version: 2.4
Name: django-adminflow
Version: 1.0.12
Summary: A premium, modern SaaS design system for the Django Admin interface with built-in 2FA, history tracking, and import/export
Author-email: Edgar <edgar@example.com>
License: MIT
Project-URL: Homepage, https://pypi.org/project/django-adminflow/
Project-URL: Documentation, https://django-adminflow.readthedocs.io/en/latest/
Project-URL: Repository, https://github.com/ramos208/Django-AdminFlow.
Project-URL: Bug Tracker, https://github.com/ramos208/Django-AdminFlow./issues
Project-URL: Changelog, https://github.com/ramos208/Django-AdminFlow./blob/master/CHANGELOG.md
Keywords: django,admin,saas,design-system,2fa,otp,history,import,export,adminflow
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: Django>=4.2
Provides-Extra: otp
Requires-Dist: django-otp>=1.4; extra == "otp"
Provides-Extra: history
Requires-Dist: django-simple-history>=3.4; extra == "history"
Provides-Extra: import-export
Requires-Dist: django-import-export>=4.0; extra == "import-export"
Requires-Dist: tablib[xlsx]>=3.5; extra == "import-export"
Requires-Dist: openpyxl>=3.1; extra == "import-export"
Provides-Extra: all
Requires-Dist: django-otp>=1.4; extra == "all"
Requires-Dist: django-simple-history>=3.4; extra == "all"
Requires-Dist: django-import-export>=4.0; extra == "all"
Requires-Dist: tablib[xlsx]>=3.5; extra == "all"
Requires-Dist: openpyxl>=3.1; extra == "all"

# django-adminflow

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

[![PyPI version](https://img.shields.io/pypi/v/django-adminflow.svg)](https://pypi.org/project/django-adminflow/)
[![Python versions](https://img.shields.io/pypi/pyversions/django-adminflow.svg)](https://pypi.org/project/django-adminflow/)
[![Django version](https://img.shields.io/badge/Django-4.2%2B-092E20?logo=django)](https://pypi.org/project/django-adminflow/)
[![License: MIT](https://img.shields.io/pypi/l/django-adminflow.svg)](https://github.com/ramos208/Django-AdminFlow./blob/master/LICENSE)
[![Docs](https://img.shields.io/badge/docs-readthedocs-blue)](https://django-adminflow.readthedocs.io/en/latest/)

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](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/login.png) | ![Dashboard](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/dashboard.png) |

| Customer List | Change Form |
|---|---|
| ![Changelist](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/changelist.png) | ![Change form](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/change_form.png) |

| Export Page | Audit History |
|---|---|
| ![Export](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/export.png) | ![History](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/history.png) |

| Import Page | 2FA / User Security |
|---|---|
| ![Import](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/import_page.png) | ![2FA](https://raw.githubusercontent.com/ramos208/Django-AdminFlow./master/docs/_static/screenshots/user_2fa.png) |

---

## 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

```bash
# 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"`

```python
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`

```python
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.

```python
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`:

```python
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

```python
# ── 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)

```python
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`

```python
# 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`

```python
# 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`:

```python
# 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:**

```json
[
  {
    "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

```python
# 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](https://django-adminflow.readthedocs.io/en/latest/)

## License

MIT
