Skip to main content

A modern Django Admin extension with enhanced UI/UX, dashboard, feedback, file management, rate limiting, IP blacklisting, and advanced admin integrations built on django-unfold.

Project description

django-whiteneuron

A modern Django Admin extension focused on UI/UX, dashboard, feedback, file management, and advanced admin integrations — built on top of django-unfold.

PyPI version Python License: MIT Downloads

django-whiteneuron

Current Version

  • 0.3.1.2

Compatibility

  • Python >= 3.11
  • Django >= 5.2.13
  • django-unfold >= 0.89.0
  • Tailwind CSS 4.x + daisyUI 5.x (for the bundled frontend styles)

Changelog

See CHANGELOG.md for the full version history.

Latest: v0.3.1.2 (2026-04-16)

Dependency: Bump django-unfold floor constraint to >=0.89.0

  • Updated: pyproject.toml — raised django-unfold minimum version from >=0.85.0 to >=0.89.0; incorporates improvements from 0.86.0–0.89.0 (compressed fields by default, removal of unbound template blocks, inline before/after templates).
  • Updated: uv.lock — lock file refreshed to reflect the updated constraint.

Installation

From PyPI (recommended)

pip install django-whiteneuron

Or with uv:

uv add django-whiteneuron

Specific version from PyPI

uv add "django-whiteneuron==0.2.37"

From GitHub tag

uv add "git+https://github.com/White-Neuron/django-whiteneuron.git@v0.2.37"

From local source

uv pip install -e .

Django Configuration

Add the apps at the top of INSTALLED_APPS:

INSTALLED_APPS = [
    "whiteneuron",
    "whiteneuron.base",
    "whiteneuron.feedbacks",
    "whiteneuron.file_management",
    "whiteneuron.contrib",
    "whiteneuron.dashboard",
    # ... your other apps
]

Add the required middleware (order matters):

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whiteneuron.base.middleware.RateLimitMiddleware",   # ← immediately after SecurityMiddleware
    "whitenoise.middleware.WhiteNoiseMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "whiteneuron.base.middleware.ReadonlyExceptionHandlerMiddleware",
    "whiteneuron.base.middleware.UserActivityMiddleware",  # ← after AuthenticationMiddleware
    "whiteneuron.base.middleware.ThreadLocalMiddleware",
]

Set the custom user model:

AUTH_USER_MODEL = "base.User"

UNFOLD Configuration Example

from django.templatetags.static import static
from django.utils.translation import gettext_lazy as _

UNFOLD = {
    "SITE_HEADER": _("White Neuron"),
    "SITE_TITLE": _("White Neuron Admin"),
    "SITE_SUBHEADER": _("Admin panel"),
    # Use SITE_ICON instead of SITE_LOGO to keep SITE_TITLE rendering correctly
    "SITE_ICON": {
        "light": lambda request: static("base/images/logo/WhiteNeuron.png"),
        "dark": lambda request: static("base/images/logo/WhiteNeuron.png"),
    },
    "SITE_FAVICONS": [
        {
            "rel": "icon",
            "sizes": "32x32",
            "type": "image/svg+xml",
            "href": lambda request: static("base/images/logo/WhiteNeuron.png"),
        },
    ],
    "SHOW_HISTORY": False,
    "SHOW_LANGUAGES": True,
    "SHOW_VIEW_ON_SITE": True,
    "SHOW_BACK_BUTTON": True,
    "DASHBOARD_CALLBACK": "whiteneuron.dashboard.views.dashboard_callback",
    "LOGIN": {
        "image": lambda request: static("base/images/login-bg.jpg"),
    },
    "STYLES": [
        lambda request: static("base/css/styles.css"),
        lambda request: static("base/css/btn-styles.css"),
        lambda request: static("base/css/loading.css"),
    ],
    "SCRIPTS": [
        lambda request: static("base/js/loading.js"),
        lambda request: static("base/js/whiteneuron.js"),
    ],
    "BORDER_RADIUS": "6px",
}

Frontend (Tailwind 4 + daisyUI 5)

Install frontend dependencies:

npm install -D @tailwindcss/cli@next daisyui@latest

Build CSS using the provided script:

bash scripts/tailwind.sh

Or run directly:

npx @tailwindcss/cli -i styles.css -o whiteneuron/static/base/css/styles.css --minify

Running the Local Example

cd whiteneuron
python manage.py migrate
python manage.py runserver

Access the admin at: http://127.0.0.1:8000/admin/

Building the Package

uv build

Or use the all-in-one build script:

bash scripts/build.sh

Rate Limiting

RateLimitMiddleware limits by IP; UserActivityMiddleware limits by authenticated user. Redis is required for accuracy in multi-worker environments.

# settings.py (hoặc env)
RATE_LIMIT_REQUESTS = 60   # số request tối đa / window (theo IP)
RATE_LIMIT_WINDOW    = 60   # tính bằng giây

USER_RATE_LIMIT_REQUESTS = 60  # theo user đã đăng nhập
USER_RATE_LIMIT_WINDOW   = 60

Corresponding env vars: RATE_LIMIT_REQUESTS, RATE_LIMIT_WINDOW, USER_RATE_LIMIT_REQUESTS, USER_RATE_LIMIT_WINDOW.

When the limit is exceeded:

  • API requests (/api/ or Accept: application/json) → JSON {"detail": "Too many requests."} with status 429.
  • Browser requests → renders 429.html template with Retry-After header.

IP Blacklist

Two protection layers operate in parallel. Both are checked before rate limiting and return 403 immediately.

Static — .env (CIDR ranges, infrastructure bans)

Loaded at startup, supports IPv4/IPv6 and CIDR:

# .env
IP_BLACKLIST=185.220.101.5,194.165.16.0/22,2001:db8::/32

Requires a Daphne/Gunicorn restart to apply new entries.

Dynamic — Django Admin + Redis (real-time)

Managed via System → IP Blacklist in the admin panel (superuser only):

  • Permanent block: leave blocked_until empty
  • Temporary block: set blocked_until → Redis TTL auto-expires, no cron needed
  • Quick block from logs: User Activity → select records → Block IP address action → Redis key set immediately, no restart needed
Request → check static env blacklist (O(1))
        → check cache.get('blacklist:dynamic:<ip>') (1 Redis GET)
        → 403 nếu match, không tốn rate limit check

Error Pages

Error templates live in whiteneuron/templates/ and are used automatically by Django when DEBUG=False:

Template Error Notes
400.html Bad Request
403.html Forbidden
404.html Not Found
429.html Too Many Requests Rendered manually by middleware, passes {{ retry_after }}
500.html Server Error

No need to register handler400/403/404/500 — Django resolves templates automatically via APP_DIRS=True.

Environment Configuration

Copy env.example to your environment file and update variables such as DATABASE, REDIS, EMAIL, and ALLOWED_HOSTS.

Contact

License

MIT License.

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_whiteneuron-0.3.1.2.tar.gz (1.4 MB view details)

Uploaded Source

Built Distribution

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

django_whiteneuron-0.3.1.2-py3-none-any.whl (1.5 MB view details)

Uploaded Python 3

File details

Details for the file django_whiteneuron-0.3.1.2.tar.gz.

File metadata

  • Download URL: django_whiteneuron-0.3.1.2.tar.gz
  • Upload date:
  • Size: 1.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for django_whiteneuron-0.3.1.2.tar.gz
Algorithm Hash digest
SHA256 a32f926de155085f6935a11f61dccc3fbc468a7ad01e3706942cc520f8efe63d
MD5 60c43f4078c190630fa5a403e36097db
BLAKE2b-256 7888f3204dbb3b26e1a1d6d13d885a81f0ad492f68d944660572ea6ca0322190

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_whiteneuron-0.3.1.2.tar.gz:

Publisher: python-publish.yml on White-Neuron/django-whiteneuron

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_whiteneuron-0.3.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for django_whiteneuron-0.3.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 945d31101f56d3ae4a334d6278f547a0df49f59bfad01e9ea5250be23fae5074
MD5 886d4d91768ddbd5ef5b3514c7547349
BLAKE2b-256 aed4f87b548b8d20eab46faf1e0349b49456e71c6ed12b346fcf55614ad9486c

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_whiteneuron-0.3.1.2-py3-none-any.whl:

Publisher: python-publish.yml on White-Neuron/django-whiteneuron

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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