Django Unfold

v1.0.0

Expert guidance for building advanced Django admin interfaces with django-unfold (v0.56+). Use this skill whenever the user mentions django-unfold, unfold ad...

0· 44·0 current·0 all-time
byIsmael J. Madalena A.@ijmadalena

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for ijmadalena/django-unfold.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Django Unfold" (ijmadalena/django-unfold) from ClawHub.
Skill page: https://clawhub.ai/ijmadalena/django-unfold
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install django-unfold

ClawHub CLI

Package manager switcher

npx clawhub@latest install django-unfold
Security Scan
Capability signals
CryptoCan make purchases
These labels describe what authority the skill may exercise. They are separate from suspicious or malicious moderation verdicts.
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
The name/description match the provided SKILL.md and reference documents: all examples and options relate to django-unfold admin features. The requested artifacts (none) and examples (ModelAdmin, UNFOLD settings, callbacks) are appropriate for a helper/reference for django-unfold.
Instruction Scope
SKILL.md and reference files are documentation and code examples only. They instruct how to configure django-unfold, give example callback functions that read process env vars (e.g., os.getenv) and use Django APIs, but they do not tell the agent to read local files, environment secrets, or transmit data to external endpoints. Example callbacks run on the Django server (normal for this context).
Install Mechanism
This skill has no install spec and includes only documentation. The SKILL.md suggests typical package installation commands (pip/poetry); nothing is downloaded or executed by the skill itself.
Credentials
No required environment variables, credentials, or config paths are declared. Some examples mention reading an environment variable (os.getenv) in sample callbacks, which is expected for app-config samples and are not actual skill requirements.
Persistence & Privilege
always is false and the skill is instruction-only; it does not request persistent presence, modify other skills, or attempt to alter system/agent configuration.
Assessment
This skill is documentation and examples for the django-unfold admin theme and appears internally consistent. Before following its installation instructions, verify the django-unfold package you install (check PyPI/GitHub repository, maintainer, and release artifacts) because the skill's metadata lists no homepage or source. Note minor doc inconsistencies (the description mentions "v0.56+" while later text states current stable 0.90.x, and the installation section includes an uncommon command `uv add` which you should confirm). Also remember sample callback code (e.g., functions referenced from UNFOLD settings) will run arbitrary Python on your server—review any callables you copy into your project to ensure they don't access secrets or perform unintended actions.

Like a lobster shell, security has layers — review code before you run it.

latestvk97453trq441gk98rtesteh23n85n0ne
44downloads
0stars
1versions
Updated 14h ago
v1.0.0
MIT-0

Django Unfold Skill

Django Unfold is a modern admin theme for Django built on Tailwind CSS. It is a drop-in enhancement of django.contrib.admin — fully compatible with all native Django admin patterns while adding UI, components, and developer-friendly features.

Current stable version: 0.90.x (Django 5.0+ required from v0.90; dropped Django 4.2)


⚠️ Critical Rules — Always Apply

Rule 1: Every ModelAdmin must inherit from unfold.admin.ModelAdmin

# ✅ CORRECT
from unfold.admin import ModelAdmin

@admin.register(MyModel)
class MyModelAdmin(ModelAdmin):
    pass

# ❌ WRONG — loses all styling and Unfold features
from django.contrib.admin import ModelAdmin  # never use this base

Rule 2: INSTALLED_APPS order — "unfold" must precede "django.contrib.admin"

INSTALLED_APPS = [
    "unfold",                           # REQUIRED FIRST
    "unfold.contrib.filters",           # optional: advanced filters
    "unfold.contrib.forms",             # optional: ArrayWidget, WysiwygWidget, crispy
    "unfold.contrib.inlines",           # optional: NonrelatedInline
    "unfold.contrib.import_export",     # optional: django-import-export
    "unfold.contrib.simple_history",    # optional: django-simple-history
    "unfold.contrib.guardian",          # optional: django-guardian
    "unfold.contrib.constance",         # optional: django-constance
    "unfold.contrib.location_field",    # optional: django-location-field
    "django.contrib.admin",             # AFTER unfold
]

Rule 3: Inlines also need Unfold base classes

from unfold.admin import StackedInline, TabularInline  # not django.contrib.admin

Rule 4: User & Group models need manual re-registration — see references/installation.md


Core ModelAdmin Options Reference

from unfold.admin import ModelAdmin
from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget
from django.db import models

@admin.register(MyModel)
class MyModelAdmin(ModelAdmin):
    # ── Changelist layout ────────────────────────────────────────────
    list_fullwidth = False               # expand to full page width
    list_filter_sheet = True             # filters as bottom sheet (False = sidebar)
    list_filter_submit = False           # show Apply button in filter panel
    list_horizontal_scrollbar_top = False
    list_disable_select_all = False

    # ── Change form UX ────────────────────────────────────────────────
    compressed_fields = True             # compact field display
    warn_unsaved_form = True             # warn before leaving unsaved
    show_add_link = True                 # show Add button
    change_form_show_cancel_button = False

    # Custom template injection (HTML snippets, not full templates)
    change_form_before_template = "myapp/before_form.html"    # inside form, top
    change_form_after_template = "myapp/after_form.html"      # inside form, bottom
    change_form_outer_before_template = "myapp/outer_top.html"
    change_form_outer_after_template = "myapp/outer_bottom.html"

    # ── Readonly field post-processing ───────────────────────────────
    readonly_preprocess_fields = {
        "html_field": "html.unescape",
        "text_field": lambda content: content.strip(),
    }

    # ── Widget overrides ─────────────────────────────────────────────
    formfield_overrides = {
        models.TextField: {"widget": WysiwygWidget},
        # ArrayField: {"widget": ArrayWidget},  # for PostgreSQL ArrayField
    }

    # ── Actions (5 types) — see references/actions.md ────────────────
    actions_list = []        # above changelist (global)
    actions_row = []         # per-row in changelist table
    actions_detail = []      # top of change form header
    actions_submit_line = [] # near Save button in change form

    # ── Conditional fields — see references/forms-fields.md ──────────
    conditional_fields = {
        "field_name": "other_field == 'value'",  # Alpine.js expression
    }

    # ── Expandable row sections — see references/forms-fields.md ─────
    list_sections = []   # [SectionClass, ...]

    # ── Datasets on change form — see references/forms-fields.md ─────
    change_form_datasets = []  # [DatasetClass, ...]

@display Decorator

Always use unfold.decorators.display, not Django's built-in.

from unfold.decorators import display

class OrderAdmin(ModelAdmin):
    list_display = ["show_customer", "show_status", "show_priority"]

    # Two-line cell: main heading + subtitle
    @display(header=True)
    def show_customer(self, obj):
        return obj.full_name, obj.email   # tuple: (main, subtitle)

    # Colored status badge mapped from field values
    @display(
        description="Status",
        ordering="status",
        label={
            "PENDING":   "warning",   # orange
            "ACTIVE":    "info",      # blue
            "COMPLETED": "success",   # green
            "FAILED":    "danger",    # red
        },
    )
    def show_status(self, obj):
        return obj.status

    # Boolean label with default color
    @display(description="VIP", label=True)
    def show_priority(self, obj):
        return obj.is_vip

→ Full @display and @action decorator docs: references/decorators.md


Reference Files — When To Read Each

Read the relevant file before implementing any feature in that area. Each reference file contains explicit pointers to related files.

Reference FileRead When You Need To...
references/installation.mdSet up from scratch, configure User/Group, run parallel admin
references/configuration.mdUnderstand any UNFOLD = {...} key: title, login, callbacks, favicons, env
references/theming.mdChange colors (OKLCH), sidebar nav, icons/badges, Tailwind custom CSS
references/actions.mdAdd list/row/detail/submitline/dropdown actions, permissions, form actions
references/filters.mdAdd text/date/dropdown/numeric/autocomplete/checkbox/radio/horizontal filters
references/tabs.mdAdd fieldset tabs, inline tabs, changelist tabs, changeform tabs, dynamic tabs
references/inlines.mdConfigure inlines: options, sortable, paginated, nested, nonrelated
references/dashboard-components.mdBuild dashboards, use components (card/chart/table/progress/tracker/cohort)
references/forms-fields.mdConditional fields, sections (expandable rows), datasets, crispy forms, JsonField
references/decorators.mdFull @display options (header, label, mapping) and @action decorator options
references/integrations.mdAll 10 third-party packages: celery-beat, import-export, guardian, constance, etc.
references/advanced.mdCustom pages, custom sites, sortable changelist, command palette, multi-language

Common Pitfalls

  • Styles missing in production → run collectstatic
  • Tailwind conflict on Unfold ≥ 0.56 → don't load a Tailwind 3 CSS file; use UNFOLD["COLORS"] or Tailwind 4
  • Custom pages not in sidebar → add manually to UNFOLD["SIDEBAR"]["navigation"]
  • Third-party admin unstyled (celery-beat, etc.) → unregister and re-register with unfold.admin.ModelAdmin
  • list_filter on Datasets → not supported; filter via get_queryset() instead
  • Django 4.2 → not supported from Unfold v0.90+

Comments

Loading comments...