8.1 Admin 配置与深度定制 本节摘要:两行代码就能让模型进后台,但真正好用 的Admin 靠 ModelAdmin 定制:列表页的列、过滤器、搜索框,编辑页的字段分组与只读保护,主从表的内联编辑,以及批量动作扩展。本节把这些定制点一次讲透,并给出 Admin 与自建后台的选择标准。 两行起步 先建一个超级用户(命令行交互式创建,自动走密码哈希): 访问 admin 路径登录,CRUD 全套即得——增删改查、删除确认、分页、第 7 章的权限面板。这"两行一个后台"的体验是 Django 出圈的头号原因。但默认列表页只有一列(模型的字符串表示),运营用起来很快会提需求。于是进入定制。
本节摘要:两行代码就能让模型进后台,但真正好用 的Admin 靠 ModelAdmin 定制:列表页的列、过滤器、搜索框,编辑页的字段分组与只读保护,主从表的内联编辑,以及批量动作扩展。本节把这些定制点一次讲透,并给出 Admin 与自建后台的选择标准。
from django.contrib import admin from .models import Article, Category, Tag, Comment admin.site.register(Article)
先建一个超级用户(命令行交互式创建,自动走密码哈希):
python manage.py createsuperuser
访问 admin 路径登录,CRUD 全套即得——增删改查、删除确认、分页、第 7 章的权限面板。这"两行一个后台"的体验是 Django 出圈的头号原因。但默认列表页只有一列(模型的字符串表示),运营用起来很快会提需求。于是进入定制。
@admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display = ("title", "author", "category", "status", "view_count", "created_at") list_filter = ("status", "category", "created_at") search_fields = ("title", "body", "author__username") list_per_page = 20 date_hierarchy = "created_at" list_select_related = ("author", "category")
每一项都直击运营痛点:

class CommentInline(admin.TabularInline): # 主从同页 model = Comment extra = 0 # 不预置空行 @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): ... fieldsets = ( ("正文", {"fields": ("title", "body")}), ("归属", {"fields": ("category", "tags", "author")}), ("发布", {"fields": ("status",), "classes": ("collapse",)}), # 可折叠分组 ) readonly_fields = ("view_count", "created_at") # 只读保护 filter_horizontal = ("tags",) # 多对多穿梭框 inlines = [CommentInline]
fieldsets 把二十个字段的编辑页切成带标题的分组,发布信息默认折叠——运营改稿时视觉负担骤减。readonly_fields 保护"只许看不许改"的字段;filter_horizontal 把多对多的多选框换成穿梭框,标签一多体验天差地别。内联则回答了"编辑文章时顺手删两条垃圾评论"的需求,不用在文章与评论两个列表页间来回跳。
列表页勾选行后的下拉动作可扩展:
actions = ["make_published"] @admin.action(description="标记为已发布") def make_published(self, request, queryset): queryset.update(status=Article.PUBLISHED) self.message_user(request, f"已发布 {queryset.count()} 篇。")
动作方法拿到整个查询集,用批量更新(第 3 章的 update),配合 message_user 给操作者反馈。审核类后台的主要工作量,常常就是三五个这样的动作。
Admin 的甜蜜区:内部人员使用、CRUD 为主、字段级的权限够用。越过边界就该自建:面向公众的页面(Admin 的模板与交互不该暴露给终端用户)、需要复杂工作流(多级审核、草稿协作)的场景、权限细到字段以外逻辑的后台。判断标准是"运营流程与 CRUD 的重合度"——重合度高用 Admin 加定制,重合度低自建页面,Admin 留给内容兜底管理。墨迹博客保持"读者用前台、编辑用 Admin"的双轨,是内容型项目的常见终态。
⚠️ 生产环境给 Admin 的入口要额外收紧:限内网或加 IP 白名单、强密码策略、有条件再上前置认证层——第 12 章安全清单的常驻项。
Admin 的深度定制能力容易让人越陷越深:列表页加导出、编辑页加预览、再加个工作流审批——配置项不够就写扩展方法,扩展方法不够就覆写模板。走到某一步你会突然发现,这个免费后台的自定义代码量已经追平一个自建后台,而它建立在你不完全可控的框架内部结构上,版本升级时定制点可能集体失效。止损线画在哪里?我的经验是三条信号:定制开始触碰 Admin 的内部调度流程(而不只是声明式配置项)是第一条;运营提出的需求与数据管理渐行渐远、越来越像业务功能是第二条;团队里只有一个人看得懂这些定制是第三条。命中任意一条,就该认真评估把这部分功能搬出 Admin、做成项目自己的页面——Admin 继续退回它擅长的数据管理本位。工具的免费是有边界的,认清边界才不会把优惠用成负债。
Admin 的便利还藏着一笔容易被忽略的性能账:它生成的查询是通用的,未必贴合你的数据规模。最典型的是外键字段——编辑文章时要选作者和分类,Admin 默认把整张表拉出来做下拉框,用户表几百人时页面开始变慢,几千人时近乎不可用。解法是给大表字段换成分页搜索组件(框架自带自动补全组件,两行配置即可),把全量加载变成按需检索。列表页同理:可筛选的外键字段每个都意味着一次全表查询,配置前先掂量数据量。墨迹博客运营半年后在 Admin 里装上连接查询的监控,才发现后台首页平时默默跑着十几条多余查询。Admin 的免费指开发成本免费,运行成本照付不误——它也是全站的一部分,同样欠下第 3 章那笔查询债。
后台有了,功能面基本齐了。上线前最后一道工序:第 9 章测试。