mcpField
U
unfold-admin

unfold-admin

github.com/0xdarkmatterデザイン・UI7864 回インストール2 週間前に更新
リポジトリ

unfold-admin について

unfold-admin は、Django の管理画面を構築・カスタマイズする開発者向けのテーマです。ModelAdmin を拡張し、フィルター、フォームウィジェット、インライン編集、ダッシュボードコンポーネントを提供します。

主な機能

  1. 01サイトのブランディングとサイドバー設定
  2. 02リスト操作と表示列の拡張
  3. 03高度なフィルターとフォームウィジェット
  4. 04ページネーション・並べ替え対応のタブ付きインライン
  5. 05ダッシュボードカードとデータパネル

活用シーン

  1. 01Django モデルの管理ページ設定
  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 管理画面

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. ダッシュボードを構築する - KPI カードに @register_component と BaseComponent を使用します

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_exportImportForm、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

リファレンスファイル

トピックごとに分けた詳細ドキュメント:

  • references/configuration.md - UNFOLD 設定辞書全般、サイドバー、タブ、テーマ設定、環境、ログイン
  • references/actions-filters.md - アクションの種類とシグネチャ、表示デコレーター、すべてのフィルタークラス
  • references/widgets-inlines.md - ウィジェットクラス一覧(35 種以上)、インラインのバリエーション、非関連インライン、フォーム
  • references/dashboard.md - ダッシュボードコンポーネント、セクション、データセット、カスタムテンプレート、Tailwind のパターン
  • references/resources.md - 公式リンク、すべてのサードパーティ連携、一般的なパターン、バージョン互換性、Unfold Studio

詳細な設定オプション、利用可能なクラスの全一覧、コード例の全容、または特定の機能領域の連携セットアップガイドが必要な場合は、該当するリファレンスファイルを参照してください。

主な外部リファレンス
リソース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 のほぼすべての機能が網羅されています。

コメント