Skip to main content

Unfold extra preview

Django Unfold Extra

PyPI - Version Build

Unofficial extension for Django Unfold admin. Adds support for Django CMS and other common django packages.

Re-registers their admin with Unfold-styled admin classes, forms and widgets, so they keep the clean, modern aesthetic of Django Unfold. It uses unobtrusive template and CSS-styling overrides where possible.

Features

  • django CMS 5.0 support: page tree, page admin, permissions, plugins and versioning
  • django-filer: full Unfold integration, including the file and image picker widgets ([filer] extra)
  • django-parler: multilingual support for your Django models
  • django-versatileimagefield: improved integration, including preview and ppoi
  • Theme sync: drive the theme from the Unfold or the django CMS switcher, or both at the same time
  • Unfold auto-update: styles can be updated from the official Unfold package via npm
  • Combines with the non-mandatory django-unfold-modal package for a unified admin experience

Requirements

  • Python 3.12+
  • django-unfold 0.92+ (<0.105)
  • django-cms 5.0.9+ (<5.1)
  • django-parler 2.3+
  • django-filer 3.0+ and djangocms-link 5.0+ for the optional [filer] / [link] extras

Unfold version: django-unfold 0.105 redesigned the admin index and several controls, so 0.5.x stays below it to keep the admin look stable for existing projects. Support for 0.105+ follows in 0.6.

Note: This package is already used in production but expect additional implementation work for your own apps and plugins. Best used when your project does not rely on external cms plugins and 3rd party packages with their own admin.

Screenshots

django CMS edit mode django CMS page permissions in the sideframe
django CMS edit mode django CMS page permissions
django CMS page permissions form django-filer directory listing
django CMS page permissions form django-filer directory listing
django-filer image change form django-filer delete confirmation
django-filer image change form django-filer delete confirmation

Installation

  1. Install the package via pip:

    pip install django-unfold-extra
    
  2. Add to your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    # Unfold theme
    "unfold",
    "unfold_extra",
    # Optional integrations
    "unfold_extra.contrib.cms",
    "unfold_extra.contrib.parler",
    "unfold_extra.contrib.auth",  # you will likely want a custom auth admin
    "unfold_extra.contrib.sites",
    "unfold_extra.contrib.filer",  # must come before "filer"
]

Make sure you have already configured Django Unfold and any optional upstream packages you use such as django CMS and django-parler.

Basic configuration

Add the shared styles integration to your settings.py:

from django.templatetags.static import static

UNFOLD = {
    "STYLES": [
        lambda request: static("unfold_extra/css/styles.css"),  # additional styles for supported integrations
    ],
}

Integrations

django CMS Support

Unfold support for all common Django CMS admin pages and plugins including:

  • Page tree: Unfold-styled pagetree, with an optional "New Page" button in the Unfold header and a language switcher
  • Page & PageContent admin: change forms with tabbed fieldsets, plus modal, sideframe, and popup contexts
  • Permissions: PageUser, PageUserGroup and GlobalPagePermission admin, with page-permission and view-restriction inlines
  • CMS User Settings
  • djangocms-versioning: versioning admin, grouper form, version action buttons, and the versioned page change form
  • Custom plugins: UnfoldCMSPluginBase with UnfoldStackedInline / UnfoldTabularInline and cms_widget_overrides
  • djangocms-link: drop-in Unfold-styled LinkPlugin covering the link MultiWidget and the attributes field ([link] extra)
  • djangocms-alias: Unfold-styled alias, category and alias content admin, the Alias plugin form and "Create Alias" popup, plus the usage and delete listings

As Django CMS uses many !important flags, a small override stylesheet is loaded after the CMS pagetree CSS to win back the conflicting declarations. Further customization is possible by compiling your own unfold_extra styles.

Configuration

Add the django CMS-specific settings to your settings.py:

   # ...
    "unfold_extra.contrib.cms",  # required to patch template loading order
    "unfold",
   # ...
from django.templatetags.static import static

UNFOLD = {
    "STYLES": [
        lambda request: static("unfold_extra/css/styles.css"),  # additional styles for supported integrations
    ],
    "SCRIPTS": [
        lambda request: static("unfold_extra/js/theme-sync.js"),  # keep django CMS theme in sync with Unfold
    ],
}

Optional: let Unfold be the single theme switch and hide theme toggle of Django CMS in toolbar.

CMS_COLOR_SCHEME_TOGGLE = False #default option

Optional: move the CMS "New Page" button into Unfold's header. Set this to False to keep the button in the CMS pagetree body. Default of Django CMS.

UNFOLD_CMS_HEADER_ADD_BUTTON = True #default option

Base Template Integration

Add {% unfold_extra_styles %} and {% unfold_extra_theme_sync %} from unfold_extra_tags to your base HTML template, after loading all CSS styles.

  • Enables Unfold admin colors in django CMS
  • Syncs the Unfold theme with django CMS (light/dark/auto)
  • Adds Unfold-styled django CMS plugin admin support
  • Exposes "COLORS" from Unfold settings on the public website for authenticated django-cms admin users
{% load static cms_tags sekizai_tags unfold_extra_tags %}
<!DOCTYPE html>
<html>
    <head>
        <title>{% block title %}{% endblock title %}</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        {% render_block "css" %}
        {% unfold_extra_styles %}
        {% unfold_extra_theme_sync %}
        ...
    </head>
...
</html>

Language Sync (Unfold ↔ CMS)

To keep the Unfold language switcher and the CMS toolbar/admin in sync, register cms_set_language from unfold_extra.views as the set_language URL before Django's i18n URLs:

from unfold_extra.views import cms_set_language

urlpatterns = [
    path("i18n/setlang/", cms_set_language, name="set_language"),
    path("i18n/", include("django.conf.urls.i18n")),
    # ...
]

When a user switches language via Unfold's sidebar, cms_set_language updates the CMS UserSettings.language before the redirect so the CMS toolbar renders in the same language on the next request.

CMS Plugins With Unfold Styling

For the general django CMS plugin model, see the official guide: https://docs.django-cms.org/en/stable/how_to/09-custom_plugins.html

This package only changes the admin side:

  • use UnfoldCMSPluginBase instead of CMSPluginBase
  • use UnfoldStackedInline or UnfoldTabularInline for plugin inlines
# cms_plugins.py
from unfold_extra.contrib.cms.plugins import UnfoldCMSPluginBase
from .models import HeroPluginModel

@plugin_pool.register_plugin
class HeroPlugin(UnfoldCMSPluginBase):
    model = HeroPluginModel
    name = _("Hero")
    render_template = "plugins/hero.html"

Most Unfold/Django admin edit options also work on plugins, including compressed_fields, fieldsets, readonly_fields, autocomplete_fields, raw_id_fields lookup popups, radio_fields, and formfield_overrides.

Use cms_widget_overrides when you need to replace plugin form widgets that should use Unfold-compatible widgets:

from unfold_extra.contrib.cms.plugins import UnfoldCMSPluginBase


class MyPlugin(UnfoldCMSPluginBase):
    cms_widget_overrides = {
        **UnfoldCMSPluginBase.cms_widget_overrides,
        SomeField: MyCustomWidget,
    }

See Unfold docs:

Page Select Widget

Unfold-styled replacements for django CMS's PageSelectWidget:

  • UnfoldPageSelectWidget — use in regular admin forms and CMS plugin forms.
  • UnfoldPageSelectInlineWidget — use in Django admin inlines. Django admin's inline cloning leaves __prefix__ inside the widget's JSON config; this variant ships a small JS patch so the site/page change handler binds to dynamically added rows.
from cms.forms.fields import PageSelectFormField
from unfold_extra.contrib.cms.widgets import (
    UnfoldPageSelectInlineWidget,
    UnfoldPageSelectWidget,
)


class MyInlineForm(forms.ModelForm):
    page = PageSelectFormField(widget=UnfoldPageSelectInlineWidget())

djangocms-link To use DjangoCMS Link Plugin with the Unfold theme for Django CMS, it must be registered with customized widgets that support Unfold styling. All functions remain intact.

INSTALLED_APPS = [
    # ...
    "djangocms_link",
    "unfold_extra.contrib.djangocms_link",  # after djangocms_link
]

Install unfold extra with link support:

pip install "django-unfold-extra[link]"

The [link] extra pulls in django-filer because djangocms-link's migrations import it (even if you never use file_link). Add filer to your INSTALLED_APPS so the migrations can run.

Advanced: drop filer by shadowing those migrations via MIGRATION_MODULES — won't work on databases already migrated with filer.

Custom Compilation via npm

The current frontend scripts live in unfold_extra/src/package.json. Run them from unfold_extra/src, for example:

npm run update:unfold
npm run tailwind:build
npm run tailwind:watch
npm run build:js

Change Colors for Django CMS

Configure colors through Unfold in settings.py using UNFOLD["COLORS"]. This is the minimal and recommended way to align the admin theme, including the shared base, primary, and font colors used by this package.

UNFOLD = {
    "COLORS": {
        "base": {
            "50": "oklch(98.5% 0.002 247.839)",
            "100": "oklch(96.7% 0.003 264.542)",
            "200": "oklch(92.8% 0.006 264.531)",
            "300": "oklch(87.2% 0.009 258.338)",
            "400": "oklch(71.4% 0.019 261.325)",
            "500": "oklch(55.1% 0.023 264.364)",
            "600": "oklch(44.6% 0.026 256.802)",
            "700": "oklch(37.3% 0.031 259.733)",
            "800": "oklch(27.8% 0.030 256.848)",
            "900": "oklch(21.0% 0.032 264.665)",
            "950": "oklch(13.0% 0.027 261.692)",
        },
        "primary": {
            "50": "oklch(97.7% 0.014 308.299)",
            "100": "oklch(94.6% 0.033 307.174)",
            "200": "oklch(90.2% 0.060 306.703)",
            "300": "oklch(82.7% 0.108 306.383)",
            "400": "oklch(72.2% 0.177 305.504)",
            "500": "oklch(62.7% 0.233 303.900)",
            "600": "oklch(55.8% 0.252 302.321)",
            "700": "oklch(49.6% 0.237 301.924)",
            "800": "oklch(43.8% 0.198 303.724)",
            "900": "oklch(38.1% 0.166 304.987)",
            "950": "oklch(29.1% 0.143 302.717)",
        },
        "font": {
            "subtle-light": "var(--color-base-500)",
            "subtle-dark": "var(--color-base-400)",
            "default-light": "var(--color-base-600)",
            "default-dark": "var(--color-base-300)",
            "important-light": "var(--color-base-900)",
            "important-dark": "var(--color-base-100)",
        },
    },
}

For CMS-specific theme adjustments beyond the shared Unfold palette, update the frontend assets in unfold_extra/src.

See the official Unfold docs:

django-filer Support

  • Full Unfold integration, including the FilerFileField / FilerImageField picker widgets.

Install with the extra and list the app before filer so it can shadow filer's templates and static files:

pip install django-unfold-extra[filer]
INSTALLED_APPS = [
    # ...
    "unfold_extra.contrib.filer",
    "filer",
]

django-parler Support

  • UnfoldTranslatableAdminMixin
  • UnfoldTranslatableStackedAdminMixin
  • UnfoldTranslatableTabularAdminMixin
  • TranslatableStackedInline, TranslatableTabularInline

Parler translation tabs

Example use:

class TranslatableAdmin(UnfoldTranslatableAdminMixin, BaseTranslatableAdmin):
   """custom translatable admin implementation"""

   # ... your code


class MyInlineAdmin(TranslatableStackedInline):
   model = MyModel
   tab = True  # Unfold inline settings
   extra = 0  # django inline settings

django-versatileimagefield Support

  • Improved unfold integration via CSS only.

Django Auth, Sites

  • Adds Unfold-based admin registrations for django.contrib.auth and django.contrib.sites.

This is for personal use. You likely want to customize this.

Release files for django-unfold-extra 0.5.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-unfold-extra 0.5.6
File Size Uploaded
django_unfold_extra-0.5.6.tar.gz 95.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-unfold-extra 0.5.6
File Interpreter ABI Platform
django_unfold_extra-0.5.6-py3-none-any.whl Python 3 none any Details

Total release size: 225.9 kB

Release files / django_unfold_extra-0.5.6.tar.gz

Download URL django_unfold_extra-0.5.6.tar.gz
Size 95.5 kB
Tags Source
SHA-256 checksum
How to use checksums
782abe529e488b2a265268d9ba83e327ee1ec0f844b2cfd2ea3e8d1237968dcb
BLAKE2b-256 checksum
How to use checksums
b9217240feddbb0f1709f8b8ca125be642118a5c8f6c7e05995c27ce06284d9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.28.1

Release files / django_unfold_extra-0.5.6-py3-none-any.whl

Download URL django_unfold_extra-0.5.6-py3-none-any.whl
Size 130.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b566671daf85204aed4027137778d874748f731acf9a4c19cdeae4b0d34733c6
BLAKE2b-256 checksum
How to use checksums
78bfbc34685ef3db0178a8e8bee90aa7704fec48075def42c3d069ed73373345
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-httpx/0.28.1

Release history Release notifications | RSS feed

This release

0.5.6 This release

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.10

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.14

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page