Skip to content

第10章:Django管理后台

10.1 Admin基础

创建超级用户

Django管理后台是一个功能强大的CRUD界面,允许管理员用户管理网站内容。首先需要创建超级用户来访问管理后台:

bash
# 创建超级用户
python manage.py createsuperuser

# 按提示输入用户名、邮箱和密码
Username (leave blank to use 'yourname'): admin
Email address: admin@example.com
Password: ********
Password (again): ********
Superuser created successfully.

通过编程方式创建超级用户:

python
# 在Django shell中创建超级用户
from django.contrib.auth.models import User

# 方法1:使用create_superuser方法
user = User.objects.create_superuser(
    username='admin',
    email='admin@example.com',
    password='securepassword'
)

# 方法2:创建普通用户后设置超级用户权限
user = User.objects.create_user(
    username='admin',
    email='admin@example.com',
    password='securepassword'
)
user.is_staff = True
user.is_superuser = True
user.save()

在部署时自动创建超级用户:

python
# management/commands/create_admin.py
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
import os

class Command(BaseCommand):
    help = 'Create a superuser if it does not exist'

    def handle(self, *args, **options):
        username = os.environ.get('DJANGO_SUPERUSER_USERNAME', 'admin')
        email = os.environ.get('DJANGO_SUPERUSER_EMAIL', 'admin@example.com')
        password = os.environ.get('DJANGO_SUPERUSER_PASSWORD', 'admin')
        
        if not User.objects.filter(username=username).exists():
            User.objects.create_superuser(username, email, password)
            self.stdout.write(
                self.style.SUCCESS(f'Superuser {username} created successfully')
            )
        else:
            self.stdout.write(
                self.style.WARNING(f'Superuser {username} already exists')
            )

注册模型

要让模型在管理后台中可见,需要在应用的admin.py文件中注册模型:

python
# models.py
from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)
    description = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        verbose_name = "分类"
        verbose_name_plural = "分类"
    
    def __str__(self):
        return self.name

class Tag(models.Model):
    name = models.CharField(max_length=50)
    slug = models.SlugField(unique=True)
    
    class Meta:
        verbose_name = "标签"
        verbose_name_plural = "标签"
    
    def __str__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
    tags = models.ManyToManyField(Tag, blank=True)
    content = models.TextField()
    excerpt = models.TextField(blank=True)
    is_published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "文章"
        verbose_name_plural = "文章"
        ordering = ['-created_at']
    
    def __str__(self):
        return self.title

# admin.py
from django.contrib import admin
from .models import Category, Tag, Article

# 基本注册方式
admin.site.register(Category)
admin.site.register(Tag)

# 使用装饰器注册
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'category', 'is_published', 'created_at']
    list_filter = ['is_published', 'category', 'created_at']
    search_fields = ['title', 'content']
    prepopulated_fields = {'slug': ('title',)}
    date_hierarchy = 'created_at'

Admin界面自定义

自定义管理后台界面以提高可用性:

python
# admin.py
from django.contrib import admin
from django.utils.html import format_html
from .models import Category, Tag, Article

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug', 'article_count', 'created_at']
    list_filter = ['created_at']
    search_fields = ['name', 'description']
    prepopulated_fields = {'slug': ('name',)}
    ordering = ['name']
    
    def article_count(self, obj):
        return obj.article_set.count()
    article_count.short_description = '文章数量'

@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug', 'article_count']
    search_fields = ['name']
    prepopulated_fields = {'slug': ('name',)}
    
    def article_count(self, obj):
        return obj.article_set.count()
    article_count.short_description = '文章数量'

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    # 列表显示
    list_display = [
        'title', 'author', 'category', 'is_published', 
        'created_at', 'preview_link'
    ]
    list_filter = ['is_published', 'category', 'tags', 'created_at', 'author']
    search_fields = ['title', 'content', 'excerpt']
    ordering = ['-created_at']
    date_hierarchy = 'created_at'
    
    # 编辑页面
    fieldsets = (
        ('基本信息', {
            'fields': ('title', 'slug', 'author', 'excerpt')
        }),
        ('内容', {
            'fields': ('content',),
            'classes': ('wide',)
        }),
        ('分类和标签', {
            'fields': ('category', 'tags')
        }),
        ('发布设置', {
            'fields': ('is_published',),
            'classes': ('collapse',)
        }),
    )
    
    # 可折叠的预设字段
    prepopulated_fields = {'slug': ('title',)}
    
    # 只读字段
    readonly_fields = ['created_at', 'updated_at']
    
    # 过滤器中的外键搜索
    autocomplete_fields = ['author', 'category']
    
    def preview_link(self, obj):
        if obj.is_published:
            return format_html(
                '<a href="{}" target="_blank">预览</a>',
                obj.get_absolute_url()
            )
        return "未发布"
    preview_link.short_description = "预览"
    
    # 自定义查询集
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        # 普通用户只能看到自己创建的文章
        return qs.filter(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)

字段显示配置

配置字段在管理后台中的显示方式:

python
# admin.py
from django.contrib import admin
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from .models import Article

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = [
        'title', 'author', 'category', 'is_published', 
        'created_at', 'word_count', 'status_badge'
    ]
    
    # 自定义字段显示
    def word_count(self, obj):
        return len(obj.content.split())
    word_count.short_description = '字数'
    word_count.admin_order_field = 'content'  # 可排序
    
    # 显示状态徽章
    def status_badge(self, obj):
        if obj.is_published:
            return format_html(
                '<span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px;">已发布</span>'
            )
        else:
            return format_html(
                '<span style="background-color: #ffc107; color: black; padding: 4px 8px; border-radius: 4px;">草稿</span>'
            )
    status_badge.short_description = '状态'
    
    # 显示富文本内容预览
    def content_preview(self, obj):
        # 截取前200个字符
        preview = obj.content[:200]
        if len(obj.content) > 200:
            preview += '...'
        return mark_safe(preview)
    content_preview.short_description = '内容预览'
    
    # 条件字段显示
    def get_list_display(self, request):
        # 超级用户可以看到所有字段
        if request.user.is_superuser:
            return self.list_display + ['content_preview']
        # 普通用户看不到某些字段
        return [field for field in self.list_display if field != 'author']

通过这些配置,你可以创建一个功能强大且用户友好的Django管理后台。

小结

Django管理后台基础功能包括:

  1. ✅ 通过命令行或编程方式创建超级用户
  2. ✅ 在admin.py中注册模型使其在后台可见
  3. ✅ 自定义Admin界面提升用户体验
  4. ✅ 配置字段显示方式和列表过滤器
  5. ✅ 使用装饰器和ModelAdmin类进行高级定制

掌握Admin基础能够快速构建内容管理系统。

下一篇

我们将学习高级Admin配置技巧。

10.2 高级Admin配置 →

目录

返回课程目录

Released under the Apache 2.0 License.