Skip to main content

A free, Bangladeshi Django admin theme & dashboard — HTMX SPA feel, live Chart.js dashboards, Bangla ⇄ English.

Project description

django-bangla-admin

A free, open-source, reusable Django admin theme & dashboard built for a Bangladeshi audience. SPA-feel via HTMX, live Chart.js dashboards, Bangla ⇄ English language switching, and a single config dict — no template editing for basic use.

License: MIT Django

Dashboard — dark, Bangla

Dashboard — light, English Changelist — dark, Bangla


Features

  • 🎨 Drop-in theme — install, add to INSTALLED_APPS, point your URLs at it. No template edits required.
  • ⚙️ One config dict (BANGLA_ADMIN) controls branding, menu, colors, dashboard.
  • SPA feel, no JS framework — HTMX partial navigation; the admin never full-reloads.
  • 🇧🇩 First-class Bangla — full Bn/En UI, instant cookie-based toggle, Bengali font stack, Bangla numerals (০১২৩).
  • 📊 Live dashboard — stat cards, line / doughnut / bar charts (Chart.js), activity feed; charts recolor on theme/lang change.
  • 🧩 Charts & KPIs from settings — declare which model, which field/status, which aggregation, which chart type in BANGLA_ADMIN; the ORM query runs for you. No Python needed. (docs)
  • 🌗 Dark default + light mode — persisted toggle; charts and components follow.
  • 📦 Zero-build, offline-friendly — prebuilt CSS, self-hosted fonts, vendored HTMX / Alpine / Chart.js. No CDN. Works on BDIX / offline VPS.

Installation

pip install django-bangla-admin
# settings.py
INSTALLED_APPS = [
    "django_bangla_admin",      # BEFORE django.contrib.admin
    "django.contrib.admin",
    # ...
]

# i18n (the Django 4.2+ correct way — cookie + LocaleMiddleware)
USE_I18N = True
LANGUAGE_CODE = "bn"
LANGUAGES = [("bn", "বাংলা"), ("en", "English")]

MIDDLEWARE = [
    # ...
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",          # after Session, before Common
    "django.middleware.common.CommonMiddleware",
    # ...
    "django_bangla_admin.middleware.HtmxShellMiddleware",  # strips shell on HX-Request
]

# Add the context processor for theme/language in templates
TEMPLATES[0]["OPTIONS"]["context_processors"] += [
    "django_bangla_admin.context_processors.bangla_admin",
]

BANGLA_ADMIN = {"site_title": "My Shop Admin", "default_language": "bn"}
# urls.py
from django.urls import path
from django_bangla_admin.sites import urls as ba_urls

urlpatterns = [path("admin/", ba_urls)]

That's it — a fully themed, Bangla, HTMX-driven admin with charts. Your existing @admin.register / admin.site.register calls work unchanged: the themed site mirrors the default admin registry automatically.

Configuration

A single BANGLA_ADMIN dict, deep-merged over the defaults:

BANGLA_ADMIN = {
    # Branding
    "site_title": "Bangla Admin",
    "site_brand": {"bn": "বাংলা অ্যাডমিন", "en": "Bangla Admin"},
    "welcome_sign": {"bn": "স্বাগতম", "en": "Welcome"},

    # Theme
    "theme": "dark",                 # "dark" | "light"
    "allow_theme_toggle": True,
    "primary_color": "#2DD4BF",

    # Language
    "default_language": "bn",
    "allow_language_toggle": True,
    "bangla_numerals": True,

    # Navigation — omit `menu` to auto-build from registered models
    "menu": [
        {"section": {"bn": "প্রধান", "en": "Main"}},
        {"label": {"bn": "ড্যাশবোর্ড", "en": "Dashboard"},
         "icon": "layout-dashboard", "url": "bangla_admin:index"},
        {"label": {"bn": "অর্ডার", "en": "Orders"},
         "icon": "shopping-cart", "model": "shop.Order"},
    ],
    "icons": {"auth.User": "user"},  # per-model Lucide icons
    "hide_apps": [], "hide_models": [],

    # Dashboard
    "dashboard": "django_bangla_admin.dashboard.default.DefaultDashboard",
    "show_dashboard": True,
}

Read values anywhere via from django_bangla_admin.conf import ba_confba_conf("theme").

Charts & KPIs from settings (no Python)

You can build the whole dashboard declaratively from BANGLA_ADMIN — say which model, which field/status, how to aggregate, and which chart type. The package runs the ORM query for you. When you declare charts and/or stat_cards, they replace the built-in demo widgets.

BANGLA_ADMIN = {
    # KPI cards across the top
    "stat_cards": [
        {"label": {"bn": "মোট অর্ডার", "en": "Total Orders"},
         "model": "shop.Order", "aggregate": "count", "icon": "shopping-cart", "trend": "+9%"},

        {"label": {"bn": "পরিশোধিত আয়", "en": "Paid Revenue"},
         "model": "shop.Order", "aggregate": "sum", "field": "total",
         "filters": {"status": "paid"}, "icon": "trending-up"},
    ],

    # Charts
    "charts": [
        # Doughnut: count orders grouped by their status (choice labels resolved)
        {"id": "orders_by_status", "kind": "doughnut",
         "title": {"bn": "অর্ডার স্ট্যাটাস", "en": "Orders by Status"},
         "model": "shop.Order", "group_by": "status", "aggregate": "count"},

        # Bar: monthly paid revenue (date field truncated to month, sum of `total`)
        {"id": "revenue_by_month", "kind": "bar",
         "title": {"bn": "মাসিক আয়", "en": "Monthly Revenue"},
         "model": "shop.Order", "group_by": "created_at", "trunc": "month",
         "aggregate": "sum", "field": "total",
         "filters": {"status": "paid"}, "limit": 12},

        # Bar: products per category (follows the FK with `__`)
        {"id": "products_per_category", "kind": "bar",
         "title": {"bn": "ক্যাটাগরি অনুযায়ী পণ্য", "en": "Products per Category"},
         "model": "shop.Product", "group_by": "category__name", "aggregate": "count"},
    ],
}

Chart options

Key Required Description
id Unique id (used as the canvas id and ?chart= key).
kind line · bar · doughnut · pie.
title String or {"bn": ..., "en": ...} dict.
model "app_label.ModelName".
group_by Field to group by. Use __ to follow relations (category__name). For a date/datetime field, add trunc.
aggregate count · sum · avg · min · max.
field Field to aggregate. Required for everything except count.
trunc For date group_by: day · week · month · year (time-series buckets, ordered chronologically).
filters Dict of ORM filters applied first, e.g. {"status": "paid", "is_active": True}. Keys support lookups (created_at__year).
limit Keep the top N groups (or last N time buckets).
size Grid width class: ba-col-12 · ba-col-6 (default) · ba-col-4 · ba-col-3.

Stat-card options

Key Required Description
label String or {"bn", "en"} dict.
model "app_label.ModelName".
aggregate count · sum · avg · min · max.
field Required for everything except count.
filters Dict of ORM filters.
icon Lucide icon name (e.g. shopping-cart, users, package).
trend / trend_dir Badge text (e.g. "+9%") and direction (up/down).

Group values are humanized automatically — fields with choices show their display label, and Bangla numerals are applied to chart axes and KPI values when the active language is Bangla. Decimal sums are returned as numbers.

Advanced: custom dashboards & metrics (Python)

For anything the declarative API can't express, drop to Python. Subclass Dashboard and point BANGLA_ADMIN["dashboard"] at it:

from django_bangla_admin.dashboard import Dashboard, StatCard, ChartWidget, ListWidget

class MyDashboard(Dashboard):
    widgets = [
        StatCard(label={"bn": "অর্ডার", "en": "Orders"},
                 value=lambda r: Order.objects.count(), icon="shopping-cart", trend="+8%"),
        ChartWidget(id="sales", kind="line",
                    title={"bn": "বিক্রি", "en": "Sales"},
                    data_url="bangla_admin:ba_chart_data", params={"metric": "sales"}),
    ]

Register fully custom chart metrics with @register_metric("name") from django_bangla_admin.dashboard.data, returning {"labels": [...], "datasets": [...]}:

from django_bangla_admin.dashboard.data import register_metric

@register_metric("sales")
def my_sales(request):
    return {"labels": [...], "datasets": [{"label": "Sales", "data": [...]}]}

Then reference it from a ChartWidget(data_url="bangla_admin:ba_chart_data", params={"metric": "sales"}).

Demo project

cd example
python manage.py migrate
python manage.py seed_demo      # creates admin/admin + sample shop data
python manage.py runserver

Open http://127.0.0.1:8000/admin/ and log in with admin / admin.

Development

pip install -e .
python -m django test tests --settings=tests.settings   # run the suite
python scripts/compile_messages.py                       # compile .po -> .mo (no gettext needed)

Tech

HTMX 2 · Alpine.js 3 · Chart.js 4 · self-hosted Hind Siliguri / Inter fonts · Django 4.2 LTS → 5.x.

License

MIT © Ifte Samul Ohy

Project details


Download files

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

Source Distribution

django_bangla_admin-0.2.1.tar.gz (144.1 kB view details)

Uploaded Source

Built Distribution

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

django_bangla_admin-0.2.1-py3-none-any.whl (150.0 kB view details)

Uploaded Python 3

File details

Details for the file django_bangla_admin-0.2.1.tar.gz.

File metadata

  • Download URL: django_bangla_admin-0.2.1.tar.gz
  • Upload date:
  • Size: 144.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for django_bangla_admin-0.2.1.tar.gz
Algorithm Hash digest
SHA256 93930e7bcf4baad8c60aed42d518a7c726009317ed2f7e56c7df9685b007947e
MD5 59f32a85fc0e637fb31d8d2435a3603a
BLAKE2b-256 ede1d54f6f3f8cd4d207e64b5b1af27e5630e57dbb17779364b7795b688af61c

See more details on using hashes here.

File details

Details for the file django_bangla_admin-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_bangla_admin-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 379899e2504e42af0c04ef01eebc3d2196c28e017fc17d1ce930b4077355a99c
MD5 018a528fa2dd474b2c7adf9f647ba017
BLAKE2b-256 0c146c220b108ec5f05eff47f0db20e4d2c2eb9f1f171cef4ce370f82caf7fcd

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 Pingdom Monitoring Sentry Error logging StatusPage Status page