django Admin后台管理详解

刚写完Article、Category、Tag模型,还在发愁加班加点手写增删改查后台、权限管理?django自带的Admin模块简直是Python后端开发的救星✨,它能基于你的模型自动生成功能完备的后台界面,帮你省下80%的基础管理开发时间。

本文你将学到:

  • ✅ 快速启用Admin并创建管理员
  • ✅ 列表页、表单页的基础美化与自定义
  • ✅ 批量操作、内联编辑等实用高级功能
  • ✅ 基于角色的权限控制
  • ✅ 简单的安全加固与外观定制

django Admin 基础操作

启用Admin(默认已开启)

django新建项目时,默认已在 INSTALLED_APPS 加入了Admin相关配置,在 urls.py 也预留了 /admin/ 入口:

# settings.py(默认片段)
INSTALLED_APPS = [
    'django.contrib.admin',  # 核心Admin
    'django.contrib.auth',   # 用户认证
    'django.contrib.contenttypes',  # 模型关联
    # ... 其他应用
]

创建超级管理员

超级管理员拥有Admin的全部权限,可以创建、修改、删除任何数据和普通管理员:

python manage.py createsuperuser

💡 提示:邮箱可以留空,密码默认要求至少8位,且不能与用户名太相似。

创建完成后,启动服务 python manage.py runserver,访问 http://127.0.0.1:8000/admin/ 即可登录。


注册模型到Admin

默认Admin界面只会显示 UserGroup 两个模型,要管理自己的应用数据,需要在应用的 admin.py 中注册。

最简单的注册

# admin.py
from django.contrib import admin
from .models import Article  # 导入你的模型

admin.site.register(Article)

刷新后台就能看到Article模型的入口,点击进入即可进行CRUD操作,但界面会非常朴素。

带基础配置的注册(推荐)

用装饰器 @admin.register() 结合 admin.ModelAdmin 子类,可以快速添加列表页显示字段、搜索栏、过滤器、自动填充等功能:

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug', 'created_at']  # 列表页显示这些字段
    prepopulated_fields = {'slug': ('name',)}       # 自动根据name生成slug
    search_fields = ['name']                         # 添加搜索栏(按name搜索)
    list_filter = ['created_at']                     # 添加右侧时间过滤器

Admin 常用自定义功能

列表页深度美化

列表页是Admin后台最常用的页面,我们可以从排序、分页、操作按钮等多方面优化:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # 1. 核心显示字段
    list_display = [
        'title', 
        'author', 
        'category', 
        'formatted_status',  # 自定义字段(后续讲)
        'created_at', 
        'view_count'
    ]
    
    # 2. 每页显示20条(默认100条)
    list_per_page = 20
    
    # 3. 可点击进入详情页的字段(默认只有第一个)
    list_display_links = ['title', 'formatted_status']
    
    # 4. 可直接在列表页编辑的字段(无需进入详情页)
    list_editable = ['status']
    
    # 5. 右侧多条件过滤器
    list_filter = ['status', 'category', 'created_at', 'author']
    
    # 6. 顶部搜索栏(可跨模型搜索,比如author__username)
    search_fields = ['title', 'content', 'author__username']
    
    # 7. 顶部日期层级导航(快速按年/月/日筛选)
    date_hierarchy = 'created_at'
    
    # 8. 默认排序(按创建时间倒序)
    ordering = ['-created_at']

自定义列表页字段(比如美化状态)

ModelAdmin 子类中定义一个方法,就能在列表页显示任何计算或美化后的内容:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # ... 前面的列表页配置 ...
    
    def formatted_status(self, obj):
        """给状态加颜色标签"""
        from django.utils.html import format_html
        
        status_colors = {
            'draft': 'orange',
            'published': 'green',
            'archived': 'gray'
        }
        color = status_colors.get(obj.status, 'black')
        
        # 用format_html生成安全的HTML
        return format_html(
            '<span style="color:{}; font-weight:bold;">{}</span>',
            color,
            obj.get_status_display()  # 获取choices的显示值
        )
    
    # 设置自定义字段的显示名称和排序依据
    formatted_status.short_description = '状态'
    formatted_status.admin_order_field = 'status'

表单页(详情页)优化

字段分组与折叠

如果模型字段很多,可以用 fieldsets 分组,甚至设置可折叠:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # ... 前面的配置 ...
    
    fieldsets = (
        ('基本信息', {
            'fields': ('title', 'author', 'category')
        }),
        ('文章内容', {
            'fields': ('content', 'summary'),
            'classes': ('wide',)  # 加宽字段
        }),
        ('发布设置', {
            'fields': ('status', 'tags', 'publish_date'),
            'classes': ('collapse',)  # 可折叠分组
        }),
        ('统计信息(只读)', {
            'fields': ('view_count', 'like_count'),
            'classes': ('collapse',)
        })
    )

多对多字段优化

默认多对多字段是一个很难用的左右选择框,用 filter_horizontalfilter_vertical 可以改成搜索+左右拖拽的样式:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    filter_horizontal = ['tags']  # 水平显示多对多
    # filter_vertical = ['tags']  # 垂直显示多对多

实用高级功能

内联编辑(一对多/多对多关系)

如果想在编辑Article时,直接编辑它的Comment(一对多)或ArticleCategory(多对多中间表),可以用 inline

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # ... 前面的配置 ...
    
    # 1. 定义内联类(TabularInline是表格样式,StackedInline是堆叠样式)
    class CommentInline(admin.TabularInline):
        model = Comment
        extra = 0  # 不显示默认的空行
        readonly_fields = ['content', 'created_at', 'user']  # 只读字段
    
    # 2. 注册内联类
    inlines = [CommentInline]

自定义批量操作

默认批量操作只有“删除选中项”,我们可以自己添加,比如“批量发布”“批量导出CSV”:

import csv
from django.http import HttpResponse
from django.contrib import messages

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # ... 前面的配置 ...
    
    actions = ['make_published', 'export_csv']
    
    def make_published(self, request, queryset):
        """批量发布选中的文章"""
        updated = queryset.update(status='published')
        self.message_user(
            request,
            f'成功发布了 {updated} 篇文章!',
            messages.SUCCESS  # 显示绿色成功提示
        )
    
    make_published.short_description = "批量发布选中文章"
    
    def export_csv(self, request, queryset):
        """批量导出CSV"""
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="articles.csv"'
        
        writer = csv.writer(response)
        writer.writerow(['标题', '作者', '分类', '状态', '创建时间'])
        
        for article in queryset:
            writer.writerow([
                article.title,
                article.author.username,
                article.category.name if article.category else '未分类',
                article.get_status_display(),
                article.created_at.strftime('%Y-%m-%d %H:%M:%S')
            ])
        
        return response
    
    export_csv.short_description = "导出选中文章为CSV"

简单的权限控制与安全

基于角色的权限控制

django Admin自带权限系统,我们可以通过 ModelAdmin 的方法动态控制权限:

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # ... 前面的配置 ...
    
    def get_queryset(self, request):
        """普通用户只能看到自己的文章,超级用户能看到所有"""
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)
    
    def has_change_permission(self, request, obj=None):
        """普通用户只能修改自己的文章"""
        if request.user.is_superuser:
            return True
        if obj is None:  # 列表页不显示修改按钮
            return True
        return obj.author == request.user
    
    def save_model(self, request, obj, form, change):
        """新建文章时自动设置作者为当前用户"""
        if not change:
            obj.author = request.user
        super().save_model(request, obj, form, change)

安全加固

  1. 修改默认Admin URL:防止黑客扫描到 /admin/
    # urls.py
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('my-secret-admin/', admin.site.urls),  # 改成复杂的路径
        # ... 其他URL
    ]
  2. 自定义站点头部:让后台更像自己的产品
    # admin.py
    admin.site.site_header = '我的个人博客后台'
    admin.site.site_title = '博客管理'
    admin.site.index_title = '欢迎回来!'

总结

django Admin虽然不是万能的(复杂的管理功能还是要自己开发),但对于快速验证产品原型、管理网站基础数据来说,绝对是不二之选。

今天我们只讲了Admin的核心功能,如果你感兴趣,可以继续探索自定义Admin视图、替换Admin模板、集成第三方Admin主题(比如 django-grappelli)等内容。

💡 最后提醒:不要把Admin暴露给普通用户,它是给网站运营者或内容编辑用的内部工具!