Python
管理后台定制
发布于 2026年7月23日
管理后台定制
Django Admin 适合内部人员管理数据,不是面向普通用户的前台页面。本篇将把默认后台改造成具备列表、搜索、筛选、批量操作和关联编辑能力的运营工具。
一、注册模型
from django.contrib import admin
from .models import Message
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
list_display = ("name", "owner", "status", "created_at")
list_filter = ("status", "created_at")
search_fields = ("name", "content", "owner__username")
ordering = ("-created_at",)
list_per_page = 30
list_display 中的方法和关联字段可能引发额外查询。数据量大时要观察后台列表的查询数量。
二、编辑页布局
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
fieldsets = (
("基本信息", {"fields": ("owner", "name", "content")}),
("发布设置", {"fields": ("status", "tags")}),
("时间信息", {
"fields": ("created_at", "updated_at"),
"classes": ("collapse",),
}),
)
readonly_fields = ("created_at", "updated_at")
filter_horizontal = ("tags",)
只读字段必须同时出现在 readonly_fields 中,否则不可编辑字段通常不会显示在表单里。
三、关联对象内联编辑
from .models import Attachment
class AttachmentInline(admin.TabularInline):
model = Attachment
extra = 0
fields = ("file", "uploaded_at")
readonly_fields = ("uploaded_at",)
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
inlines = [AttachmentInline]
TabularInline 更紧凑,StackedInline 更适合字段较多的子对象。
四、自定义列表字段
from django.contrib import admin
@admin.display(description="摘要", ordering="content")
def content_preview(self, obj):
return obj.content[:30]
把它加入 list_display:
list_display = ("name", "content_preview", "status", "created_at")
不要返回拼接的未转义 HTML。确实需要 HTML 时使用 format_html()。
五、批量操作
@admin.action(description="将选中留言设为已发布")
def make_published(modeladmin, request, queryset):
updated = queryset.update(status=Message.Status.PUBLISHED)
modeladmin.message_user(request, f"已发布 {updated} 条留言。")
@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
actions = [make_published]
queryset.update() 不会调用每个对象的 save(),也不会触发 pre_save/post_save 信号。如果业务依赖这些行为,应逐条处理或把规则提取到明确的服务函数中。
六、自动填写当前用户
def save_model(self, request, obj, form, change):
if not change or obj.owner_id is None:
obj.owner = request.user
super().save_model(request, obj, form, change)
如果普通后台用户不能选择 owner,可通过 exclude、get_readonly_fields() 或自定义表单限制。
七、后台权限
def get_queryset(self, request):
queryset = super().get_queryset(request)
if request.user.is_superuser:
return queryset
return queryset.filter(owner=request.user)
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
还可重写 has_view_permission()、has_add_permission()、has_change_permission()。后台权限仍需配合用户组和最小权限原则。
八、查询优化
list_select_related = ("owner",)
def get_queryset(self, request):
return super().get_queryset(request).prefetch_related("tags")
大数据量后台还应注意:
- 搜索字段是否有合适索引。
date_hierarchy和精确总数查询的成本。- 外键下拉框是否过大,可使用
autocomplete_fields或raw_id_fields。
autocomplete_fields = ("owner",)
被自动完成引用的模型后台必须配置 search_fields。
九、后台品牌信息
admin.site.site_header = "留言平台管理后台"
admin.site.site_title = "留言平台"
admin.site.index_title = "数据管理"
深度改造后台界面前应评估成本。复杂业务流程、面向客户的功能或高度定制交互,通常更适合独立开发页面。
十、常见问题
- 模型不显示:应用未注册、模型未注册或当前用户无权限。
- 自定义字段报错:方法名没有加入
list_display,或签名不正确。 - 批量操作没有触发业务逻辑:
update()绕过了模型save()和保存信号。 - 外键下拉极慢:数据量大,应使用
autocomplete_fields。 - 普通员工看到全部数据:只配置了界面字段,未限制
get_queryset()和权限。
十一、本篇检查清单
- 能配置后台列表、搜索、筛选和排序。
- 能组织编辑页和内联关联对象。
- 能实现安全的批量操作。
- 能控制不同后台用户的数据范围。
- 能识别 Admin 适用范围,不把它当作全部前台页面。
上一篇:类视图与通用视图 | 下一篇:配置、中间件、信号与管理命令