Django管理界面
一、今日学习内容概述
学习模块 | 重要程度 | 预计学时 | 主要内容 |
---|---|---|---|
基础管理配置 | ⭐⭐⭐⭐⭐ | 1小时 | ModelAdmin基本配置 |
自定义管理界面 | ⭐⭐⭐⭐⭐ | 2小时 | 界面定制、动作添加 |
内联模型管理 | ⭐⭐⭐⭐ | 1.5小时 | 内联显示、关联编辑 |
高级定制功能 | ⭐⭐⭐⭐ | 1.5小时 | 权限控制、界面美化 |
二、基础模型定义
# models.py
from django.db import models
from django.contrib.auth.models import Userclass Category(models.Model):name = models.CharField('分类名称', max_length=100)description = models.TextField('描述', blank=True)created_at = models.DateTimeField('创建时间', auto_now_add=True)class Meta:verbose_name = '分类'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass Product(models.Model):STATUS_CHOICES = [('draft', '草稿'),('published', '已发布'),('archived', '已归档'),]name = models.CharField('商品名称', max_length=200)category = models.ForeignKey(Category, on_delete=models.CASCADE,related_name='products',verbose_name='分类')price = models.DecimalField('价格', max_digits=10, decimal_places=2)stock = models.PositiveIntegerField('库存')description = models.TextField('描述')status = models.CharField('状态',max_length=10,choices=STATUS_CHOICES,default='draft')created_by = models.ForeignKey(User,on_delete=models.CASCADE,verbose_name='创建者')created_at = models.DateTimeField('创建时间', auto_now_add=True)updated_at = models.DateTimeField('更新时间', auto_now=True)class Meta:verbose_name = '商品'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass ProductImage(models.Model):product = models.ForeignKey(Product,on_delete=models.CASCADE,related_name='images',verbose_name='商品')image = models.ImageField('图片', upload_to='products/')is_primary = models.BooleanField('是否主图', default=False)created_at = models.DateTimeField('创建时间', auto_now_add=True)class Meta:verbose_name = '商品图片'verbose_name_plural = verbose_name
三、自定义管理界面
3.1 基础管理类
# admin.py
from django.contrib import admin
from django.utils.html import format_html
from .models import Category, Product, ProductImage@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):list_display = ('name', 'description', 'products_count', 'created_at')search_fields = ('name',)list_per_page = 20def products_count(self, obj):return obj.products.count()products_count.short_description = '商品数量'class ProductImageInline(admin.TabularInline):model = ProductImageextra = 1fields = ('image', 'is_primary')@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):# 列表页配置list_display = ('name', 'category', 'price', 'stock', 'status', 'created_by', 'created_at', 'get_image')list_filter = ('status', 'category', 'created_at')search_fields = ('name', 'description')list_editable = ('price', 'stock', 'status')list_per_page = 20# 详情页配置fieldsets = (('基本信息', {'fields': ('name', 'category', 'price', 'stock')}),('详细描述', {'fields': ('description',),'classes': ('collapse',)}),('状态信息', {'fields': ('status', 'created_by')}))# 内联显示图片inlines = [ProductImageInline]def get_image(self, obj):primary_image = obj.images.filter(is_primary=True).first()if primary_image:return format_html('<img src="{}" width="50" height="50" />',primary_image.image.url)return '无图片'get_image.short_description = '主图'def save_model(self, request, obj, form, change):if not change: # 新建商品时obj.created_by = request.usersuper().save_model(request, obj, form, change)def get_queryset(self, request):qs = super().get_queryset(request)if request.user.is_superuser:return qsreturn qs.filter(created_by=request.user)
3.2 自定义动作
# admin.py
from django.contrib import admin, messages
from django.http import HttpResponse
import csv@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):actions = ['export_as_csv', 'publish_products', 'archive_products']def export_as_csv(self, request, queryset):meta = self.model._metafield_names = [field.name for field in meta.fields]response = HttpResponse(content_type='text/csv')response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)writer = csv.writer(response)writer.writerow(field_names)for obj in queryset:writer.writerow([getattr(obj, field) for field in field_names])return responseexport_as_csv.short_description = '导出所选商品为CSV'def publish_products(self, request, queryset):updated = queryset.update(status='published')self.message_user(request,f'成功发布 {updated} 个商品',messages.SUCCESS)publish_products.short_description = '发布所选商品'def archive_products(self, request, queryset):updated = queryset.update(status='archived')self.message_user(request,f'成功归档 {updated} 个商品',messages.SUCCESS)archive_products.short_description = '归档所选商品'
四、自定义表单
# forms.py
from django import forms
from .models import Productclass ProductAdminForm(forms.ModelForm):class Meta:model = Productfields = '__all__'def clean_price(self):price = self.cleaned_data.get('price')if price and price < 0:raise forms.ValidationError('价格不能为负数')return price# admin.py中使用自定义表单
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):form = ProductAdminForm
五、管理界面流程图
六、高级定制功能
6.1 自定义后台主题
# admin.py
admin.site.site_header = '商品管理系统'
admin.site.site_title = '商品管理'
admin.site.index_title = '欢迎使用商品管理系统'# templates/admin/base_site.html
{% extends "admin/base.html" %}
{% load static %}{% block extrastyle %}
<style>#header {background: #2c3e50;color: #fff;}.module h2, .module caption {background: #34495e;}div.breadcrumbs {background: #34495e;}a:link, a:visited {color: #2c3e50;}
</style>
{% endblock %}
6.2 自定义列表显示
# admin.py
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):def get_list_display(self, request):"""动态设置列表显示字段"""if request.user.is_superuser:return ('name', 'category', 'price', 'stock', 'status', 'created_by', 'created_at', 'get_image')return ('name', 'category', 'price', 'stock', 'status')def get_readonly_fields(self, request, obj=None):"""动态设置只读字段"""if request.user.is_superuser:return ()if obj: # 编辑时return ('created_by', 'created_at')return ('created_at',)
6.3 自定义过滤器
# admin.py
from django.contrib.admin import SimpleListFilterclass StockStatusFilter(SimpleListFilter):title = '库存状态'parameter_name = 'stock_status'def lookups(self, request, model_admin):return (('out', '无库存'),('low', '库存不足'),('enough', '库存充足'),)def queryset(self, request, queryset):if self.value() == 'out':return queryset.filter(stock=0)if self.value() == 'low':return queryset.filter(stock__gt=0, stock__lt=10)if self.value() == 'enough':return queryset.filter(stock__gte=10)@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):list_filter = (StockStatusFilter, 'status', 'category')
七、内联模型示例
# admin.py
from django.contrib import admin
from .models import Order, OrderItemclass OrderItemInline(admin.TabularInline):model = OrderItemextra = 1fields = ('product', 'quantity', 'price')raw_id_fields = ('product',)def get_readonly_fields(self, request, obj=None):if obj: # 如果是编辑已存在的订单return ('price',)return ()@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):list_display = ('order_number', 'customer', 'total_amount', 'status', 'created_at')list_filter = ('status', 'created_at')search_fields = ('order_number', 'customer__username')inlines = [OrderItemInline]readonly_fields = ('order_number', 'total_amount')
八、权限控制
# admin.py
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):def has_add_permission(self, request):"""控制添加权限"""return request.user.has_perm('products.add_product')def has_change_permission(self, request, obj=None):"""控制修改权限"""if not obj:return True# 只允许超级管理员和创建者修改return request.user.is_superuser or obj.created_by == request.userdef has_delete_permission(self, request, obj=None):"""控制删除权限"""if not obj:return True# 只允许超级管理员删除return request.user.is_superuser
九、总结
-
今日要点回顾:
- Django管理界面的基本配置
- 自定义管理界面的外观和功能
- 内联模型的使用方法
- 权限控制的实现
-
应用场景:
- 内容管理系统
- 电商后台管理
- 数据维护界面
- 运营管理系统
-
注意事项:
- 合理设置权限
- 优化查询性能
- 注意数据安全
- 保持界面友好
-
扩展建议:
- 集成富文本编辑器
- 添加数据导入导出
- 自定义管理命令
- 添加数据统计功能
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!