IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我也会在其它平台持续发布最新文章,助你少走弯路。
大家好,我是IT策士。前面三节课我们把模型建好、索引加好、迁移理顺了,数据库里现在还是"空荡荡"的。今天我们就来做两件大事:把 Django Admin 变成运营人员的利器 ,同时给数据库灌入第一批数据,让项目有点"活气儿"。
Django Admin 是 Django 最引以为傲的"杀手锏"之一。你只需要写很少的代码,就能得到一个功能完整的后台管理系统。电商项目里,管理员需要上下架商品、查看订单、管理用户,这些都可以在 Admin 中实现。
一、创建超级管理员账号
要登录 Admin,首先需要一个超级用户。在项目根目录执行:
bash
python manage.py createsuperuser
按提示输入用户名、邮箱、密码:
bash
Username (leave blank to use 'kali'): admin
Email address: admin@example.com
Password:
Password (again):
Superuser created successfully.
现在启动开发服务器:
bash
python manage.py runserver
访问 http://127.0.0.1:8000/admin/,用刚创建的用户名和密码登录,你会看到 Django 自带的后台界面,目前只显示了默认的"用户"和"组"。这是因为我们还没有把自定义模型注册进去。
二、注册模型到 Admin
2.1 用户模块
编辑 apps/users/admin.py:
bash
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User, Address
@admin.register(User)
class UserAdmin(BaseUserAdmin):
# 在列表页显示的字段
list_display = ('id', 'username', 'phone', 'email', 'is_staff', 'is_active', 'date_joined')
# 可按哪些字段筛选
list_filter = ('is_staff', 'is_active')
# 搜索字段
search_fields = ('username', 'phone', 'email')
# 编辑页分组
fieldsets = BaseUserAdmin.fieldsets + (
('额外信息', {'fields': ('phone', 'email_active')}),
)
@admin.register(Address)
class AddressAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'receiver', 'phone', 'province', 'city', 'district', 'is_default')
search_fields = ('receiver', 'phone')
list_filter = ('province', 'city')
2.2 商品模块
编辑 apps/products/admin.py:
bash
from django.contrib import admin
from .models import Category, SPU, SKU, ProductImage
class SKUInline(admin.TabularInline):
"""在 SPU 详情页内嵌 SKU 编辑"""
model = SKU
extra = 1 # 默认显示一个空白行
class ProductImageInline(admin.TabularInline):
"""在 SKU 详情页内嵌图片编辑"""
model = ProductImage
extra = 1
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'parent', 'level', 'sort', 'is_active')
list_filter = ('is_active', 'level')
search_fields = ('name',)
@admin.register(SPU)
class SPUAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'brand', 'category', 'create_time')
search_fields = ('name', 'brand')
list_filter = ('category',)
inlines = [SKUInline] # 内嵌 SKU 管理
@admin.register(SKU)
class SKUAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'spu', 'price', 'stock', 'sales', 'is_active')
search_fields = ('name',)
list_filter = ('is_active', 'spu__category')
inlines = [ProductImageInline] # 内嵌图片管理
# 可以在列表页直接编辑上下架状态
list_editable = ('is_active', 'price')
@admin.register(ProductImage)
class ProductImageAdmin(admin.ModelAdmin):
list_display = ('id', 'sku', 'image', 'is_main', 'sort')
2.3 购物车模块
编辑 apps/cart/admin.py:
bash
from django.contrib import admin
from .models import CartItem
@admin.register(CartItem)
class CartItemAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'sku', 'quantity', 'is_checked', 'create_time')
list_filter = ('is_checked',)
search_fields = ('user__username', 'sku__name')
2.4 订单模块
编辑 apps/orders/admin.py:
bash
from django.contrib import admin
from .models import Order, OrderItem
class OrderItemInline(admin.TabularInline):
model = OrderItem
extra = 0
readonly_fields = ('sku_name', 'sku_specs', 'price', 'quantity')
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ('id', 'order_no', 'user', 'total_amount', 'status', 'create_time')
list_filter = ('status', 'create_time')
search_fields = ('order_no', 'user__username')
readonly_fields = ('order_no', 'address_snapshot', 'create_time', 'update_time')
inlines = [OrderItemInline]
# 可在此处添加自定义操作(如批量改为"已发货"等)
@admin.register(OrderItem)
class OrderItemAdmin(admin.ModelAdmin):
list_display = ('id', 'order', 'sku_name', 'price', 'quantity')
search_fields = ('sku_name', 'order__order_no')
2.5 支付模块
编辑 apps/payment/admin.py:
bash
from django.contrib import admin
from .models import Payment
@admin.register(Payment)
class PaymentAdmin(admin.ModelAdmin):
list_display = ('id', 'order', 'trade_no', 'amount', 'status', 'create_time')
list_filter = ('status',)
search_fields = ('trade_no', 'order__order_no')
readonly_fields = ('order', 'create_time', 'update_time')
保存所有文件后,刷新 Admin 页面,你会看到左侧导航栏出现了我们自定义的五个模块:用户、地址、分类、SPU、SKU、图片、购物车、订单、订单商品、支付记录。整个后台瞬间有模有样了。
三、Admin 高级定制------让后台更好用
3.1 list_display 也能显示关联字段
在 SKUAdmin 中我们用 spu__category 实现了跨表显示:
bash
list_filter = ('is_active', 'spu__category')
这相当于在 SQL 中做了 JOIN,无需额外写代码。
3.2 使用 list_editable 实现列表页快速编辑
bash
list_editable = ('is_active', 'price')
这样在 SKU 列表页就可以直接勾选"是否上架"或修改价格,无需点进详情页。
3.3 自定义 Admin 操作
在 OrderAdmin 中我们可以添加批量操作,比如"批量标记为已发货"。在 OrderAdmin 类内部添加:
bash
actions = ['mark_as_shipped']
def mark_as_shipped(self, request, queryset):
updated = queryset.filter(status=1).update(status=2) # 待发货 -> 待收货
self.message_user(request, f'已成功将 {updated} 个订单标记为已发货。')
mark_as_shipped.short_description = '批量标记为已发货'
刷新订单列表页,在动作下拉框里就能看到"批量标记为已发货"了。
3.4 自定义 Admin 模板标题
编辑 django_ecommerce/urls.py(临时测试),也可以在 settings.py 中通过 ADMIN_SITE_HEADER 等变量修改站点标题。在 settings.py 末尾加上:
bash
ADMIN_SITE_HEADER = "电商后台管理系统"
ADMIN_SITE_TITLE = "电商管理"
ADMIN_INDEX_TITLE = "欢迎使用电商管理后台"
刷新 Admin,顶部的"Django 管理"就变成了"电商后台管理系统"。
四、数据初始化------给空表"填饱肚子"
有了后台,理论上我们可以逐条手动录入商品,但那太慢了。我们需要一种自动化的方式来批量导入基础数据。Django 提供了几种方案:fixture 、自定义管理命令 、数据迁移。推荐使用自定义管理命令,因为它最灵活,而且可以调用项目的完整代码。
4.1 创建管理命令目录结构
在 apps/products 下新建以下目录和文件:
bash
apps/products/
└── management/
├── __init__.py
└── commands/
├── __init__.py
└── init_product_data.py
确保每个 __init__.py 都是空文件(告诉 Python 这是一个包)。
4.2 编写初始化脚本
编辑 apps/products/management/commands/init_product_data.py:
bash
from django.core.management.base import BaseCommand
from products.models import Category, SPU, SKU, ProductImage
from decimal import Decimal
class Command(BaseCommand):
help = '初始化商品基础数据'
def handle(self, *args, **kwargs):
self.stdout.write('开始初始化数据...')
# 1. 创建分类
electronics = Category.objects.create(name='电子产品', level=1, sort=1)
phone = Category.objects.create(name='手机', parent=electronics, level=2, sort=1)
computer = Category.objects.create(name='电脑', parent=electronics, level=2, sort=2)
clothing = Category.objects.create(name='服装', level=1, sort=2)
men = Category.objects.create(name='男装', parent=clothing, level=2, sort=1)
women = Category.objects.create(name='女装', parent=clothing, level=2, sort=2)
self.stdout.write(self.style.SUCCESS('分类创建完成'))
# 2. 创建 SPU
spu_iphone = SPU.objects.create(
name='iPhone 15', brand='Apple',
desc='Apple 最新款智能手机', category=phone
)
spu_macbook = SPU.objects.create(
name='MacBook Pro 16', brand='Apple',
desc='专业级笔记本电脑', category=computer
)
spu_tshirt = SPU.objects.create(
name='纯棉 T 恤', brand='Uniqlo',
desc='舒适百搭的日常 T 恤', category=men
)
self.stdout.write(self.style.SUCCESS('SPU 创建完成'))
# 3. 创建 SKU
sku1 = SKU.objects.create(
spu=spu_iphone, name='iPhone 15 128GB 午夜色',
specs={'颜色': '午夜色', '存储': '128GB'},
price=Decimal('5999.00'), cost_price=Decimal('4500.00'),
stock=100, sales=0, is_active=True
)
sku2 = SKU.objects.create(
spu=spu_iphone, name='iPhone 15 256GB 午夜色',
specs={'颜色': '午夜色', '存储': '256GB'},
price=Decimal('6999.00'), cost_price=Decimal('5500.00'),
stock=50, sales=0, is_active=True
)
sku3 = SKU.objects.create(
spu=spu_macbook, name='MacBook Pro 16 M3 Pro 512GB',
specs={'芯片': 'M3 Pro', '存储': '512GB'},
price=Decimal('19999.00'), cost_price=Decimal('16000.00'),
stock=30, sales=0, is_active=True
)
sku4 = SKU.objects.create(
spu=spu_tshirt, name='纯棉 T 恤 白色 M',
specs={'颜色': '白色', '尺码': 'M'},
price=Decimal('99.00'), cost_price=Decimal('50.00'),
stock=200, sales=0, is_active=True
)
sku5 = SKU.objects.create(
spu=spu_tshirt, name='纯棉 T 恤 黑色 L',
specs={'颜色': '黑色', '尺码': 'L'},
price=Decimal('99.00'), cost_price=Decimal('50.00'),
stock=150, sales=0, is_active=True
)
self.stdout.write(self.style.SUCCESS('SKU 创建完成'))
# 4. 给部分 SKU 创建主图(先不传实际图片,只演示占位)
# 实际开发中可配合 File 对象或图片 URL 导入
self.stdout.write(self.style.SUCCESS('初始化完成!'))
4.3 执行初始化命令
bash
python manage.py init_product_data
控制台输出:
bash
开始初始化数据...
分类创建完成
SPU 创建完成
SKU 创建完成
初始化完成!
现在我们回到 Admin 后台,点击"商品分类"、"SPU"、"SKU",就能看到刚刚灌入的数据了。运营人员可以在后台进一步完善图片、修改库存和价格。
五、补充:fixture 方式快速导入/导出数据
有时你需要把数据库中的数据导出为 JSON 文件,备份或共享。Django 的 fixture 功能可以胜任。
导出数据:
bash
python manage.py dumpdata products --indent 2 > products_fixture.json
导入数据(另一环境或清库后恢复):
bash
python manage.py loaddata products_fixture.json
fixture 适用于表结构不变的数据备份,但逻辑复杂的初始化还是推荐自定义管理命令。
六、总结与下集预告
今天我们让 Django Admin 真正为电商项目服务了:
-
创建了超级管理员,成功登录后台;
-
将所有自定义模型注册到 Admin,并通过内联、列表编辑、自定义操作等高级特性大幅提升了后台的可用性;
-
编写了自定义管理命令,一键初始化了商品分类、SPU、SKU 的基础数据;
-
了解了 fixture 的导出和导入,为后续数据备份打下基础。
至此,我们的项目骨架、数据库、后台管理、初始数据已经全部就位,接下来就是面向用户的功能开发了。第 5 天,我将带你做项目基础配置的收尾工作:整合 Bootstrap 5 静态文件、配置模板路径、处理媒体文件上传,打造一个漂亮统一的前端基础。别忘了追更!
想了解更多还其它平台搜索「IT策士」,一起升级 IT 思维 !
*本文为《Django 从 0 到 1 打造完整电商平台》系列第 4 篇,作者:IT策士,未经授权禁止转载。
*