Overview
The Django CMS Simple Admin Style is a lightweight alternative to the comprehensive Django CMS Admin Style. Its goal is to refine the Django CMS interface with minimalistic changes:
Standardizing color schemes with Django CMS.
Making minimal CSS adjustments like adding button borders for interface consistency.
Restraining from interfering with Django’s admin styling.
Removing headers from Django CMS’ sidebar and modal.
All stylesheets are combined into a single CSS file under 20kB.
Browser Support
The Django CMS Simple Admin Style uses CSS nesting to maintain a small stylesheet size, which makes it incompatible with Internet Explorer. It does work with all current versions of modern browsers. Visit CanIUse for more information on CSS features compatibility.
Installation
For a manual installation:
Run pip install djangocms-simple-admin-style
Add djangocms_simple_admin_style to your INSTALLED_APPS just before 'django.contrib.admin'
Configuration
While the Django CMS Simple Admin Style overrides Django admin’s base_site.html, you can still customize this page using the source of templates/admin/base_site.html and override the templates included in various blocks. For instance, you can insert your own CSS in templates/admin/inc/extrastyle.html.
The following additional settings can be set:
CMS_ENABLE_UPDATE_CHECK = True Set to False to disable the update notification.
CMS_UPDATE_CHECK_TYPE = ‘patch’ Set to ‘patch’ to get only patch notifications. (major = x.x.x, minor = 5.x.x, patch = 5.0.x)
CMS_LEGACY_STYLE Force the legacy (django CMS 4) admin styling on or off. If unset, the legacy style is auto-detected on django CMS < 5.1 or when the project’s base.html declares <html data-cms-theme="4">. Set to True to force the legacy style, or False to force the new style and skip auto-detection.
The update checker does not gather or record any data - however, it does query pypi.org for the latest version number.
Contributing
To contribute:
Set up the development environment with nvm use and npm install.
Changes should be made in private/, never in the built *.min.css:
private/djangocms-simple-admin.css is served on Django 6.1 and later, which stacks admin form inputs beneath their labels natively (ticket #34643).
private/djangocms-simple-admin-legacy.css is served on Django 6.0 and earlier, and forces that layout itself.
{% admin_style_css %} picks between them by django.VERSION. A change that is not specific to one admin generation usually belongs in both.
Use . ./minify-css to minify the updated CSS files. CI fails if the committed minified files do not match their sources.
Lint the stylesheets with npx stylelint "private/*.css".
Running the tests
The suite needs Django and a few small helpers, but not django CMS – it runs a plain Django admin, so it can be tested against every supported Django rather than only the ones a given django CMS release pins:
pip install django beautifulsoup4 soupsieve packaging python -m django test tests --settings=tests.settings
The package itself is deliberately not installed: the tests import it from the working directory, so its django-cms dependency – which would pin Django and collapse the matrix – never enters the picture. (pip install -e ".[test]" installs the same helpers, but pulls django CMS in with them.)
CI runs this against Django 4.2, 5.0, 5.1, 5.2, 6.0, 6.1 and Django main. Each run tests whichever stylesheet admin_style_css() would actually serve for that version, so the legacy sheet is exercised below 6.1 and the current one from 6.1 up.
What the tests do
- tests/test_selector_coverage.py
Renders a sample of real admin pages and asserts that every rule in the stylesheet still matches something. When a new Django release renames or restructures admin markup, this names the exact rules that stopped applying instead of leaving you to spot it in a screenshot – the failure mode that produced ol.breadcrumbs, .titles-and-tools and [aria-current="page"].
- tests/test_stylesheet_sanity.py
Structural checks needing no rendered HTML, over both stylesheets. Most usefully, it rejects a type selector that names no real element, which is almost always a class selector that lost its leading dot – valid CSS that silently matches nothing.
- tests/test_templatetags.py
Unit tests for the template tags, including the legacy-style auto-detection and its fallbacks.
Admin pages used for coverage
tests/pages.py renders these pages against tests.testapp, whose Widget model and ModelAdmin are built to exercise the widgets the stylesheets target. A rule only counts as live if it matches on at least one of them, so this list is what the coverage check is worth:
- index, app_list
The dashboard and the single-app list: module tables, section links and the colMS sidebar layout. A log entry is created first so the “recent actions” list is populated – it is the only place the admin uses .mini.
- changelist
Result table, sortable headers, action bar, filter sidebar, search bar, date hierarchy and the paginator. list_per_page is 5 against 12 fixtures, so the list really paginates.
- changelist_page2, changelist_search, changelist_filtered
The states the base changelist does not show: a current paginator page, a submitted search, and a selected filter.
- add, change
The widest page by far. Between them they render text, slug, textarea, URL, email, integer, decimal, split date/time, date, checkbox, choice select and a read-only UUID field; a foreign key in a related-widget-wrapper; a many-to-many as filter_horizontal; wide, collapse and multi-field (.fieldBox) fieldsets; a fieldset description containing markup (Django renders descriptions with |safe); and both a stacked and a tabular inline.
- add_invalid
The same form submitted with errors, for .errorlist and the .flex-container.errors wrapper.
- delete, action_confirm
Both delete-confirmation layouts: the single-object page and the delete_selected action interstitial.
- view_only_change
The change page as seen by a staff user with view-but-not-change permission. Django renders the submit row’s .closelink only when the form cannot be saved, so this read-only page is the one place that markup appears.
- history
The object history table.
- popup
An add form with ?_popup=1, for the .popup body class and its submit row.
- user_changelist, user_add, user_change
The auth user pages, which the stylesheets target by name via the app-auth and model-user body classes and the password field.
- password_change
The admin password change form.
- with_message
A successful submission followed through the redirect, so .messagelist markup is present.
- login
The logged-out login form.
When a coverage test fails
A reported rule is dead on the Django version being tested. Either the admin changed and the rule needs updating, or the rule is obsolete and should be deleted. If neither applies, the rule belongs in one of three lists in tests/test_selector_coverage.py, all of which carry a reason per entry:
- NOT_SERVER_RENDERED
Markup this suite can never see, because a script builds it in the browser (.selector from SelectFilter2.js, the .datetimeshortcuts icons) or another package ships it (django CMS, django-parler, django-select2). A browser-driven visual regression suite would cover these; this one says so rather than pretending.
- VERSION_GATED
Rules for markup a newer Django introduced, correctly dead below it. The boundaries are established by running the suite against each release, not guessed.
- KNOWN_STALE
Pre-existing dead rules, pinned so the suite starts green. Each entry is a to-do, not an excuse.
The first two lists are the interesting ones to keep short. Entries are checked against the stylesheets, so a rule that is later deleted cannot linger in a list.
To add a page to the sample, add it to render_all() in tests/pages.py; adding a widget type usually means a field on tests/testapp/models.py and its ModelAdmin.
Icons
djangocms-simple-admin-style uses icons from Bootstrap Icons. These icons are licensed under MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file djangocms_simple_admin_style-2.1.1.tar.gz.
File metadata
- Download URL: djangocms_simple_admin_style-2.1.1.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
941fe1593d1d9af72aaa5d117557089cb60c5588ca292d619a61437e0087ac44
|
|
| MD5 |
3175f3f32d811f335d834093b3bb21bc
|
|
| BLAKE2b-256 |
d634094753cff641457ec9140b86d6f230a8d4d45ebf6c913e3904d83165da1d
|
File details
Details for the file djangocms_simple_admin_style-2.1.1-py3-none-any.whl.
File metadata
- Download URL: djangocms_simple_admin_style-2.1.1-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d848d461e285d2e11b905c93248f8cc0a10b9043bba3abf760262234f260e6d7
|
|
| MD5 |
0f92b4abe4a509557fbc78b7d1f6ee90
|
|
| BLAKE2b-256 |
f97636352d377226e7d63afc98c065be81e8419a08841f7b62995613aa755748
|