mcpField
U
unfold-admin

unfold-admin

github.com/0xdarkmatter设计与 UI7864 次安装2 周前更新
代码仓库

关于 unfold-admin

unfold-admin 是用于 Django 项目的管理界面主题,面向构建和定制后台的开发者。它扩展 Django ModelAdmin,提供过滤器、表单控件、内联编辑和仪表盘组件。

主要功能

  1. 01自定义站点品牌与侧边栏
  2. 02扩展列表操作与显示列
  3. 03高级过滤器和表单控件
  4. 04支持分页、排序和标签式内联
  5. 05仪表盘卡片及数据面板

适用场景

  1. 01为 Django 模型配置后台管理页面
  2. 02在列表中添加筛选器和批量操作
  3. 03为关联数据构建标签式编辑区
  4. 04在后台仪表盘展示 KPI 卡片

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/0xdarkmatter/claude-mods --skill unfold-admin

安装后在 Claude Code 中输入/unfold-admin确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
actions-filters.md
configuration.md
dashboard.md
resources.md
widgets-inlines.md

详细介绍

Django Unfold Admin

基于 Tailwind CSS、HTMX 和 Alpine.js 的现代 Django 管理主题。以精致、功能丰富的界面替代 Django 默认管理界面。

快速开始

安装
# settings.py - unfold MUST be before django.contrib.admin
INSTALLED_APPS = [
    "unfold",
    "unfold.contrib.filters",          # advanced filters
    "unfold.contrib.forms",            # array/wysiwyg widgets
    "unfold.contrib.inlines",          # nonrelated inlines
    "unfold.contrib.import_export",    # styled import/export
    "unfold.contrib.guardian",         # django-guardian integration
    "unfold.contrib.simple_history",   # django-simple-history integration
    "unfold.contrib.constance",        # django-constance integration
    "unfold.contrib.location_field",   # django-location-field integration
    # ...
    "django.contrib.admin",
]
最简管理界面
from unfold.admin import ModelAdmin

@admin.register(MyModel)
class MyModelAdmin(ModelAdmin):
    pass  # inherits Unfold styling
站点配置

替换默认的 AdminSite,或通过设置中的 UNFOLD 字典进行配置。完整的设置参考请参阅 references/configuration.md。

UNFOLD = {
    "SITE_TITLE": "My Admin",
    "SITE_HEADER": "My Admin",
    "SITE_SYMBOL": "dashboard",  # Material Symbols icon name
    "SIDEBAR": {
        "show_search": True,
        "navigation": [
            {
                "title": _("Navigation"),
                "items": [
                    {
                        "title": _("Dashboard"),
                        "icon": "dashboard",
                        "link": reverse_lazy("admin:index"),
                    },
                ],
            },
        ],
    },
}

核心工作流

构建 Unfold 管理界面时,请按以下顺序进行:

  1. 配置站点 - UNFOLD 设置字典(品牌标识、侧边栏、主题)
  2. 注册模型 - 扩展 unfold.admin.ModelAdmin
  3. 增强显示效果 - 使用 @display 装饰器设置列表列
  4. 添加操作 - 使用 @action 装饰器添加行、列表、详情和提交操作
  5. 配置筛选器 - 用 Unfold 筛选器类替换默认筛选器
  6. 覆盖控件 - 通过 formfield_overrides 应用 Unfold 控件
  7. 设置内联 - 使用 Unfold 的内联类,并启用标签页、分页和排序
  8. 构建仪表板 - 使用 @register_component + BaseComponent 创建 KPI 卡片

ModelAdmin 属性

Unfold 为 Django 的 ModelAdmin 扩展了以下附加属性:

属性类型用途
list_fullwidthbool使用全宽更改列表(无侧边栏)
list_filter_submitbool在筛选器中添加提交按钮
list_filter_sheetbool在滑出式面板中显示筛选器
compressed_fieldsbool缩小表单中的字段间距
warn_unsaved_formbool离开未保存的表单前发出警告
ordering_fieldstr用于拖动排序的字段名称
hide_ordering_fieldbool隐藏排序字段列
list_horizontal_scrollbar_topbool在列表顶部显示滚动条
list_disable_select_allbool禁用“全选”复选框
change_form_show_cancel_buttonbool在表单上显示取消按钮
actions_listlist全局更改列表操作
actions_rowlist更改列表中的逐行操作
actions_detaillist更改表单上的操作
actions_submit_linelist表单提交区域中的操作
actions_list_hide_defaultbool隐藏默认列表操作
actions_detail_hide_defaultbool隐藏默认详情操作
conditional_fieldsdict控制字段可见性的 JS 表达式
change_form_datasetslist用于更改表单的 BaseDataset 子类
list_sectionslist用于列表的 TableSection/TemplateSection
list_sections_classesstr分区的 CSS 网格类
readonly_preprocess_fieldsdict转换只读字段内容
add_fieldsetslist为添加表单单独设置字段集(类似 UserAdmin)
模板注入点

在更改列表或更改表单之前/之后插入自定义 HTML:

class MyAdmin(ModelAdmin):
    # Changelist
    list_before_template = "myapp/list_before.html"
    list_after_template = "myapp/list_after.html"
    # Change form (inside <form> tag)
    change_form_before_template = "myapp/form_before.html"
    change_form_after_template = "myapp/form_after.html"
    # Change form (outside <form> tag)
    change_form_outer_before_template = "myapp/outer_before.html"
    change_form_outer_after_template = "myapp/outer_after.html"
条件字段

根据其他字段的值显示/隐藏字段(Alpine.js 表达式):

class MyAdmin(ModelAdmin):
    conditional_fields = {
        "premium_features": "plan == 'PRO'",
        "discount_amount": "has_discount == true",
    }

操作系统

共有 4 种操作类型,每种都有不同的签名。完整参考请参阅 references/actions-filters.md。

from unfold.decorators import action
from unfold.enums import ActionVariant

# List action (no object context)
@action(description=_("Rebuild Index"), icon="sync", variant=ActionVariant.PRIMARY)
def rebuild_index(self, request):
    # process...
    return redirect(request.headers["referer"])

# Row action (receives object_id)
@action(description=_("Approve"), url_path="approve")
def approve_row(self, request, object_id):
    obj = self.model.objects.get(pk=object_id)
    return redirect(request.headers["referer"])

# Detail action (receives object_id, shown on change form)
@action(description=_("Send Email"), permissions=["send_email"])
def send_email(self, request, object_id):
    return redirect(reverse_lazy("admin:myapp_mymodel_change", args=[object_id]))

# Submit line action (receives obj instance, runs on save)
@action(description=_("Save & Publish"))
def save_and_publish(self, request, obj):
    obj.published = True
操作组(下拉菜单)
actions_list = [
    "primary_action",
    {
        "title": _("More"),
        "variant": ActionVariant.PRIMARY,
        "items": ["secondary_action", "tertiary_action"],
    },
]
权限
@action(permissions=["can_export", "auth.view_user"])
def export_data(self, request):
    pass

def has_can_export_permission(self, request):
    return request.user.is_superuser

Display 装饰器

增强 list_display 列。请参阅 references/actions-filters.md。

from unfold.decorators import display

# Colored status labels
@display(description=_("Status"), ordering="status", label={
    "active": "success",    # green
    "pending": "info",      # blue
    "warning": "warning",   # orange
    "inactive": "danger",   # red
})
def show_status(self, obj):
    return obj.status

# Rich header with avatar
@display(description=_("User"), header=True)
def show_header(self, obj):
    return [
        obj.full_name,           # primary text
        obj.email,               # secondary text
        obj.initials,            # badge text
        {"path": obj.avatar.url, "width": 24, "height": 24, "borderless": True},
    ]

# Interactive dropdown
@display(description=_("Teams"), dropdown=True)
def show_teams(self, obj):
    return {
        "title": f"{obj.teams.count()} teams",
        "items": [{"title": t.name, "link": t.get_admin_url()} for t in obj.teams.all()],
        "striped": True,
        "max_height": 200,
    }

# Boolean checkmark
@display(description=_("Active"), boolean=True)
def is_active(self, obj):
    return obj.is_active

筛选器

Unfold 提供高级筛选器类。请参阅 references/actions-filters.md。

from unfold.contrib.filters.admin import (
    TextFilter, RangeNumericFilter, RangeDateFilter, RangeDateTimeFilter,
    SingleNumericFilter, SliderNumericFilter, RelatedDropdownFilter,
    RelatedCheckboxFilter, ChoicesCheckboxFilter, AllValuesCheckboxFilter,
    BooleanRadioFilter, CheckboxFilter, AutocompleteSelectMultipleFilter,
)

class MyAdmin(ModelAdmin):
    list_filter_submit = True  # required for input-based filters
    list_filter = [
        ("salary", RangeNumericFilter),
        ("status", ChoicesCheckboxFilter),
        ("created_at", RangeDateFilter),
        ("category", RelatedDropdownFilter),
        ("is_active", BooleanRadioFilter),
    ]
自定义文本筛选器
class NameFilter(TextFilter):
    title = _("Name")
    parameter_name = "name"

    def queryset(self, request, queryset):
        if self.value() in EMPTY_VALUES:
            return queryset
        return queryset.filter(name__icontains=self.value())

控件

覆盖表单控件以应用 Unfold 样式。请参阅 references/widgets-inlines.md。

from unfold.widgets import (
    UnfoldAdminTextInputWidget, UnfoldAdminSelectWidget, UnfoldAdminSelect2Widget,
    UnfoldBooleanSwitchWidget, UnfoldAdminColorInputWidget,
    UnfoldAdminSplitDateTimeWidget, UnfoldAdminImageFieldWidget,
)
from unfold.contrib.forms.widgets import WysiwygWidget, ArrayWidget

class MyAdmin(ModelAdmin):
    formfield_overrides = {
        models.TextField: {"widget": WysiwygWidget},
        models.ImageField: {"widget": UnfoldAdminImageFieldWidget},
    }
带图标的文本输入框
widget = UnfoldAdminTextInputWidget(attrs={
    "prefix_icon": "search",
    "suffix_icon": "euro",
})

内联

Unfold 内联支持标签页、分页、排序和非关联模型。请参阅 references/widgets-inlines.md。

from unfold.admin import TabularInline, StackedInline
from unfold.contrib.inlines.admin import NonrelatedStackedInline

class OrderItemInline(TabularInline):
    model = OrderItem
    tab = True          # show as tab
    per_page = 10       # paginated
    ordering_field = "weight"  # drag-to-reorder
    hide_title = True
    collapsible = True

字段集标签页

使用 "classes": ["tab"] 将字段集分组到标签页中:

fieldsets = [
    (None, {"fields": ["name", "email"]}),  # always visible
    (_("Profile"), {"classes": ["tab"], "fields": ["bio", "avatar"]}),
    (_("Settings"), {"classes": ["tab"], "fields": ["theme", "notifications"]}),
]

仪表盘组件

构建 KPI 卡片和自定义仪表盘小组件。请参阅 references/dashboard.md。

from unfold.components import BaseComponent, register_component
from django.template.loader import render_to_string

@register_component
class ActiveUsersComponent(BaseComponent):
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["children"] = render_to_string("myapp/kpi_card.html", {
            "total": User.objects.filter(is_active=True).count(),
            "label": "Active Users",
        })
        return context

在设置中配置:

UNFOLD = {
    "DASHBOARD_CALLBACK": "myapp.views.dashboard_callback",
}

分区(变更列表面板)

在变更列表视图中嵌入相关数据面板:

from unfold.sections import TableSection, TemplateSection

class RecentOrdersSection(TableSection):
    related_name = "order_set"
    fields = ["id", "total", "status"]
    height = 380

class ChartSection(TemplateSection):
    template_name = "myapp/chart.html"

class MyAdmin(ModelAdmin):
    list_sections = [RecentOrdersSection, ChartSection]
    list_sections_classes = "lg:grid-cols-2"

数据集(变更表单面板)

在变更表单中嵌入模型列表:

from unfold.datasets import BaseDataset

class RelatedItemsDatasetAdmin(ModelAdmin):
    list_display = ["name", "status"]
    search_fields = ["name"]

class RelatedItemsDataset(BaseDataset):
    model = RelatedItem
    model_admin = RelatedItemsDatasetAdmin
    tab = True  # show as tab

class MyAdmin(ModelAdmin):
    change_form_datasets = [RelatedItemsDataset]

分页器

使用无限滚动分页:

from unfold.paginator import InfinitePaginator

class MyAdmin(ModelAdmin):
    paginator = InfinitePaginator
    show_full_result_count = False
    list_per_page = 20

第三方集成

Unfold 为常见的 Django 包提供带样式的封装。请参阅 references/resources.md 获取完整的设置指南。

包Unfold 模块设置
django-import-exportunfold.contrib.import_export使用 ImportForm、ExportForm、SelectableFieldsExportForm
django-guardianunfold.contrib.guardian带样式的 guardian 集成
django-simple-historyunfold.contrib.simple_history带样式的历史记录集成
django-constanceunfold.contrib.constance带样式的 constance 配置
django-location-fieldunfold.contrib.location_field位置小组件
django-modeltranslation兼容将 TabbedTranslationAdmin 与 ModelAdmin 混用
django-celery-beat兼容(重新接线)取消注册 5 个模型,再使用 Unfold 重新注册
django-moneyunfold.widgetsUnfoldAdminMoneyWidget
djangoql兼容将 DjangoQLSearchMixin 与 ModelAdmin 混用
django-crispy-forms兼容提供 Unfold 模板包
# Multiple inheritance - Unfold ModelAdmin always last
@admin.register(MyModel)
class MyAdmin(DjangoQLSearchMixin, SimpleHistoryAdmin, GuardedModelAdmin, ModelAdmin):
    pass

内置模板组件

Unfold 附带可复用的模板组件,可用于仪表盘和自定义页面:

组件路径关键变量
卡片unfold/components/card.htmltitle、footer、label、icon
柱状图unfold/components/chart/bar.htmldata(JSON)、height、width
折线图unfold/components/chart/line.htmldata(JSON)、height、width
进度条unfold/components/progress.htmlvalue、title、description
表格unfold/components/table.htmltable、card_included、striped
按钮unfold/components/button.htmlname、href、submit
追踪器unfold/components/tracker.htmldata
队列unfold/components/cohort.htmldata
{% load unfold %}
{% component "MyKPIComponent" %}{% endcomponent %}

用户管理表单

Unfold 提供带样式的 Django 身份验证管理表单:

from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm

@admin.register(User)
class UserAdmin(BaseUserAdmin, ModelAdmin):
    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm

参考文件

按主题分类的详细文档:

如需详细配置选项、可用类的完整列表、完整代码示例,或特定功能领域的集成设置指南,请阅读相关参考文件。

重要外部参考资料
资源URL
文档https://unfoldadmin.com/docs/
GitHubhttps://github.com/unfoldadmin/django-unfold
演示应用(Formula)https://github.com/unfoldadmin/formula
在线演示https://demo.unfoldadmin.com
Material Symbols(图标)https://fonts.google.com/icons

不确定实现模式时,请参考 Formula 演示仓库中的 formula/admin.py 和 formula/settings.py——其中涵盖了几乎所有 Unfold 功能。

评论

支持 Markdown