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.1

Compatibility

  • Python >= 3.11
  • Django >= 5.2.13
  • django-unfold >= 0.85.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.1 (2026-04-16)

Fix: permission_viewer_callback missing unauthenticated guard; add md2html-tailwind4 dependency

  • Fixed: base/utils.pypermission_viewer_callback now checks request.user.is_authenticated before returning True, preventing unauthenticated (anonymous) users from passing the permission check.
  • Fixed: base/settings.py — UNFOLD navigation Feedbacks menu item permission callback changed from permission_non_guest_callback to permission_viewer_callback for consistency.
  • Added: pyproject.toml — added md2html-tailwind4>=1.0.0 as a dependency.

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.1.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.1-py3-none-any.whl (1.5 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_whiteneuron-0.3.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 238da24ea0c60d57ae92133d2e606d5aebcc96dde95538672895e075abe0b184
MD5 f1f479bf0cdf4a34a914ccf11e36d43e
BLAKE2b-256 8c241cdfa479965f726f6b3cc47412d8864ae31a7986d50a701ae52f26dc93e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_whiteneuron-0.3.1.1.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.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_whiteneuron-0.3.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1fb60966aec531090aad0d2c53295ccac346ba47e59f706d73034ddf271dd9de
MD5 bd00308bba31ec701cfcfcee13d1967d
BLAKE2b-256 24a3cae426e3ee9d2a8a106dcc61fd1c6af8c36b2c35802927e2d6ab3bbb9a8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_whiteneuron-0.3.1.1-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