Django Admin 指南

使用 ModelAdmin 选项、内联模型、自定义动作和高级配置定制 Django admin 界面。

1. 基本 ModelAdmin

from django.contrib import admin
from django.utils.html import format_html
from .models import Article

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display   = ("title", "author", "status", "view_count", "created_at")
    list_editable  = ("status",)
    list_per_page  = 25

    list_filter    = ("status", "category", "created_at")
    search_fields  = ("title", "content", "author__name")
    date_hierarchy = "created_at"

    readonly_fields = ("slug", "view_count", "created_at")
    prepopulated_fields = {"slug": ("title",)}

    fieldsets = (
        (None, {"fields": ("title", "slug", "author", "category")}),
        ("内容", {"fields": ("content", "cover_image")}),
        ("发布", {"fields": ("status", "published_at"), "classes": ("collapse",)}),
    )

2. 自定义 Admin 动作

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    actions = ["publish_selected", "export_csv"]

    @admin.action(description="发布选中文章")
    def publish_selected(self, request, queryset):
        updated = queryset.filter(status="draft").update(status="published")
        self.message_user(request, f"已发布 {updated} 篇文章。")

    @admin.action(description="导出为 CSV")
    def export_csv(self, request, queryset):
        import csv
        from django.http import HttpResponse
        response = HttpResponse(content_type="text/csv")
        response["Content-Disposition"] = 'attachment; filename="articles.csv"'
        writer = csv.writer(response)
        writer.writerow(["ID", "标题", "作者", "状态"])
        for obj in queryset:
            writer.writerow([obj.pk, obj.title, obj.author.name, obj.status])
        return response

3. 内联模型

class OrderItemInline(admin.TabularInline):
    model = OrderItem
    extra = 1
    fields = ("product", "quantity", "unit_price")

@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
    inlines = [OrderItemInline]
    list_display = ("order_number", "customer", "total", "status")

4. 覆盖管理视图

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    def get_urls(self):
        urls = super().get_urls()
        custom = [
            path("analytics/", self.admin_site.admin_view(self.analytics_view)),
        ]
        return custom + urls

    # 仅显示当前用户的文章
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if not request.user.is_superuser:
            return qs.filter(author=request.user)
        return qs