Django Grappelli
Django Grappelli is a grid-based alternative/extension, essentially a 'jazzy skin,' for the Django administration interface. It aims to improve the usability and aesthetics of the standard Django admin. The current stable version is 4.0.3, which is compatible with Django 5.x. Grappelli's release cycle is closely tied to Django's major versions, ensuring compatibility with the latest stable Django releases.
Common errors
-
ModuleNotFoundError: No module named 'grappelli' or ImportError: No module named grappellidjango.contrib.
cause The `django-grappelli` package is not installed or not correctly added to `INSTALLED_APPS`.fixRun `pip install django-grappelli` to install the package. Then, ensure `'grappelli'` is correctly listed in `INSTALLED_APPS` in your `settings.py`. -
NoReverseMatch at /admin/ Reverse for 'grp_related_lookup' with arguments '()' and keyword arguments '{}' not found.cause The `grappelli.urls` are not correctly included in your project's `urls.py`, or are placed after `admin.site.urls`.fixIn your `urls.py`, ensure `path('grappelli/', include('grappelli.urls'))` is present and placed *before* `path('admin/', admin.site.urls)`. -
Django admin interface is unstyled or partially styled after installing grappelli.
cause The `grappelli` app is listed after `django.contrib.admin` in `INSTALLED_APPS`, or `collectstatic` was not run.fixMove `'grappelli'` to appear *before* `'django.contrib.admin'` in `INSTALLED_APPS` in `settings.py`. Also, ensure you have run `python manage.py collectstatic` to gather Grappelli's static files. -
ValueError: invalid literal for int() with base 10: 'some_string' (often related to admin URLs).
cause This can occur due to an incorrect regular expression in your URLconf, where a URL pattern expects an integer but receives a string with non-digit characters. This is often a misconfiguration of custom admin URLs interacting with Grappelli.fixReview your `urls.py` patterns, especially those involving `grappelli.urls` or custom admin views, to ensure regular expressions correctly capture expected numeric values or that all URL parameters are strings. This is less common with modern `path()` syntax but can still happen with `re_path()`.
Warnings
- breaking Grappelli versions are tightly coupled with Django versions. Grappelli 4.x explicitly requires Django 5.x. Upgrading Django without also upgrading Grappelli (or vice-versa) can lead to broken admin interfaces and runtime errors.
- gotcha Incorrect order of 'grappelli' in INSTALLED_APPS. Grappelli must always be listed BEFORE 'django.contrib.admin' for its templates and static files to override the default Django admin correctly. Failing to do so results in an unstyled or partially styled admin interface, or missing functionality.
- gotcha Missing `django.template.context_processors.request`. The Grappelli Dashboard and Switch User features rely on this context processor being enabled in your `TEMPLATES` settings. Without it, these features will not function correctly and may raise errors.
- breaking Django's URL pattern syntax changed from `url()` (regex-based) to `path()` (simpler) starting with Django 2.0. Older Grappelli configurations or tutorials might use `url()` from `django.conf.urls`, which is deprecated and removed in newer Django versions.
- gotcha Issues with custom user models and the 'Switch User' feature. If you are using a custom user model where `is_superuser` or `is_staff` are defined as properties rather than fields, the 'Switch User' feature might break.
Install
-
pip install django-grappelli
Imports
- grappelli
INSTALLED_APPS = ('grappelli', 'django.contrib.admin', ...) - grappelli.urls
from django.conf.urls import url, include # for Django 2.0+ projects
from django.urls import path, include urlpatterns = [ path('grappelli/', include('grappelli.urls')), # Grappelli URLS path('admin/', admin.site.urls), ]
Quickstart
import os
from pathlib import Path
# Assuming a standard Django project setup for settings.py and urls.py
# --- settings.py ---
BASE_DIR = Path(__file__).resolve().parent.parent
INSTALLED_APPS = [
'grappelli', # Grappelli must be before django.contrib.admin
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# ... other apps
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'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',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request', # Required for Grappelli Dashboard/Switch User
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# --- urls.py ---
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('grappelli/', include('grappelli.urls')), # grappelli URLS
path('admin/', admin.site.urls), # admin site
# ... other url patterns
]
# After setting up, run:
# python manage.py collectstatic
# python manage.py runserver
# Then visit /admin/ or /grappelli/ (though typically /admin/ is redirected to the grappelli-skinned admin).