news 2026/10/12 4:41:02

Day 05 · Admin 后台:不写一行前端代码的管理系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day 05 · Admin 后台:不写一行前端代码的管理系统

摘要:老板说"给我做一个后台管理页面",你是不是下意识就准备打开 Vue + ElementUI 开始写前端了?停!如果你用 Django,这一步完全可以跳过。Django Admin 是 Django 自带的杀手级功能——把 Model 注册进去,一个完整的管理后台立刻就出来了:列表、搜索、过滤、增删改查、内联编辑,全都不用写一行前端代码。本篇从零搭起商城的 Admin 后台,覆盖自定义列表、过滤器、搜索框、内联编辑,教你怎么用 AI 批量生成 Admin 配置,最后附上实用的安全加固方案。成本:0。


后台管理页面,不想自己写前端怎么办?

做过商城系统的应该都知道,后台管理页面是个"不得不做但又很无聊"的东西。

商品要管理、分类要管理、订单要管理、用户也要管理。每个模块都要:

  • 一个列表页(能看、能搜索、能过滤)
  • 一个详情页(能看、能改)
  • 一个新增页(能填、能校验)

用传统方式写,光这 4 个模块的前端代码,1500 行起步。

而用了 Django Admin,这几行就够了:

@admin.register(Goods)classGoodsAdmin(admin.ModelAdmin):pass

就这几行,商品的管理后台就出来了。列表、新增、编辑、删除,全都有了。

而且这不是 Demo,这是真实可用的生产级管理界面。Django Admin 诞生的目的就是让你把时间花在业务逻辑上,而不是重复造轮子。

说个真实案例:我之前给一个客户做内部管理系统,客户要管理 20 多个数据表。传统方式光前端页面就得写两三个月。用了 Django Admin,三天交付。客户看到后台还以为是专门找人做的前端——其实一行前端代码都没写。

这就是 Django Admin 的能力:注册 Model 即得管理界面。


Admin 是怎么工作的

动手之前先花两分钟搞明白原理,后面定制才不会懵。

用户请求 /admin/ ↓ Django 找到对应的 Model ↓ 调用对应的 Admin 类(如果有自定义的话) ↓ 渲染模板(用 Django 自带的 admin 模板) ↓ 返回 HTML 页面

核心概念就几个:

1. ModelAdmin 类——每个 Model 对应一个 Admin 类,通过继承admin.ModelAdmin定制界面。配置列表显示哪些字段、哪些可搜索、哪些可过滤。

2. admin.site.register()——把 Model 和 Admin 类注册到 Admin 站点。不传自定义类直接admin.site.register(Category)也能用,但所有字段都显示,功能能用不够好看。所以通常写ModelAdmin子类来控制细节。

3. Admin 模板系统——自带一套完整模板,支持新增、编辑、删除、批量操作、导出 CSV。可覆盖,但大部分场景不用动。

4. 底层逻辑——Admin 本质就是根据你的 Model 字段定义,自动生成对应的 HTML 表单。Model 有什么字段,Admin 就显示什么输入框。这也是它强大的原因:和数据库结构完全绑定,不会出现前后端数据不一致。


动手:从注册 Model 到完整后台

第一步:确认 Day03 的 Model

Day03 我们已经定义了 5 个核心 Model(在mall/models.py里):CustomUser、Category、Goods、Order、OrderItem。这里不重复贴了,没建的回去补 Day03。

下面所有 Admin 配置都基于这些 Model。

第二步:写 Admin 配置文件

在mall应用下创建admin.py:

# mall/admin.pyfromdjango.contribimportadminfrom.modelsimportCustomUser,Category,Goods,Order,OrderItem# 注册用户管理@admin.register(CustomUser)classCustomUserAdmin(admin.ModelAdmin):list_display=["username","email","phone","is_staff","date_joined"]list_filter=["is_staff","is_active","date_joined"]search_fields=["username","email","phone"]readonly_fields=["date_joined","last_login"]# 只读字段,不能编辑ordering=["-date_joined"]# 注册分类管理@admin.register(Category)classCategoryAdmin(admin.ModelAdmin):list_display=["name","parent","sort","id"]list_filter=["parent"]search_fields=["name"]ordering=["sort","id"]# 注册商品管理(重点配置)@admin.register(Goods)classGoodsAdmin(admin.ModelAdmin):# ========== 列表页配置 ==========list_display=["name","category","price","stock","status","created_at"]list_per_page=20# 每页 20 条,默认 100 太多list_editable=["status","stock"]# 列表页直接改,不用进详情页list_filter=["category","status","created_at"]# 右侧过滤器search_fields=["name","description"]# 顶部搜索框ordering=["-created_at"]# ========== 详情页配置 ==========fieldsets=[("基本信息",{"fields":["name","category","price","stock"]}),("商品详情",{"fields":["status","image","description"]}),("时间信息",{"fields":["created_at","updated_at"],"classes":["collapse"]}),]readonly_fields=["created_at","updated_at"]date_hierarchy="created_at"# 顶部日期层级导航# 订单项内联(嵌在订单详情页里显示)classOrderItemInline(admin.TabularInline):model=OrderItem extra=0# 默认不显示空白行readonly_fields=["goods","price","quantity"]can_delete=False# 不允许在后台删订单项,保持数据完整性# 注册订单管理@admin.register(Order)classOrderAdmin(admin.ModelAdmin):list_display=["order_no","user","total_amount","status","receiver","created_at"]list_filter=["status","created_at"]search_fields=["order_no","receiver","phone","user__username"]readonly_fields=["order_no","total_amount","created_at","updated_at"]ordering=["-created_at"]date_hierarchy="created_at"inlines=[OrderItemInline]# 关键:订单项内联进订单详情页fieldsets=[("订单信息",{"fields":["order_no","user","total_amount","status","created_at"]}),("收货信息",{"fields":["receiver","phone","address"]}),("备注",{"fields":["remark"],"classes":["collapse"]}),]# ========== 自定义批量操作 ==========actions=["mark_shipped","mark_cancelled"]@admin.action(description="批量标记为已发货")defmark_shipped(self,request,queryset):updated=queryset.filter(status=1).update(status=2)self.message_user(request,f"成功标记{updated}个订单为已发货")@admin.action(description="批量标记为已取消")defmark_cancelled(self,request,queryset):updated=queryset.update(status=4)self.message_user(request,f"成功标记{updated}个订单为已取消")

各配置项的作用:

  • list_display:列表页显示哪些列
  • list_filter:右侧过滤器,快速筛选
  • search_fields:顶部搜索框,模糊匹配
  • list_editable:列表页直接编辑
  • fieldsets:详情页字段分组,表单更清晰
  • inlines:把 OrderItem 嵌到 Order 详情页,直接看订单商品列表
  • date_hierarchy:按日期层级导航,点年→展开月→点月→看日
  • actions:自定义批量操作,一键发货/取消

界面长这样(文字描述):

登录/admin/后,左侧菜单:

+ 认证和授权 - 用户 + MALL - 商品分类 - 商品 - 订单

点"商品"进列表页:顶部有搜索框;右侧有过滤器(按分类、状态、时间);表格列是商品名、分类、单价、库存、状态、创建时间;"状态"和"库存"两列可以直接点改;每页 20 条,底部有分页器。

点某个订单进去:顶部是订单基本信息(订单号、用户、总金额、状态);中间是收货信息;最下面是内联的订单项表格(商品、单价、数量)。

第三步:创建超级管理员

cd/app/data/所有对话/主对话/meiyada_mall python manage.py createsuperuser# 按提示输入用户名、邮箱、密码

或者用命令直接创建(适合自动化场景,逻辑片段):

# mall/management/commands/create_admin.py# 用法: python manage.py create_adminfromdjango.core.management.baseimportBaseCommandfromdjango.contrib.authimportget_user_model User=get_user_model()classCommand(BaseCommand):defhandle(self,*args,**options):ifnotUser.objects.filter(username="admin").exists():User.objects.create_superuser(username="admin",email="admin@meiyada.com",password="your-strong-password-here"# 上线前改成强密码)self.stdout.write(self.style.SUCCESS("✅ 超级管理员创建成功"))else:self.stdout.write("⚠️ admin 用户已存在,跳过")

第四步:配置 Admin 站点

在settings.py里配置整个站点的标题:

# settings.py 中追加ADMIN_SITE_HEADER="梅雅达商城管理后台"# 顶部标题ADMIN_SITE_TITLE="梅雅达商城管理"# 浏览器标签标题ADMIN_INDEX_TITLE="欢迎使用梅雅达商城后台"# 首页标题

效果:顶部导航栏从默认的"Django 管理"变成"梅雅达商城管理后台"。

第五步:收集静态文件 + 运行

python manage.py collectstatic# 收集 Admin 的 CSS/JS,否则样式难看python manage.py runserver0.0.0.0:8000

浏览器打开http://127.0.0.1:8000/admin/,用刚才的超级管理员登录。

你会看到:左侧导航树(用户、商品分类、商品、订单);右侧主内容区列表页有搜索框、过滤器、分页信息;每行右侧有编辑/删除按钮;顶部显示"梅雅达商城管理后台"。


用 AI 批量生成 Admin 配置

5 个 Model 手写配置还行,但如果有 20 多个数据表呢?一个一个手写,光list_display、list_filter、search_fields这些字段名就能写到眼花。

这就是 AI 擅长的活——批量生成重复性配置。

把下面的提示词发给 Trae 或 Cursor,几秒拿到完整代码:

我有一个 Django 应用 mall,包含以下 Model: - CustomUser:用户(username, email, phone, avatar, is_staff, date_joined) - Category:分类(name, parent, sort) - Goods:商品(name, category, price, stock, status, image, description, created_at, updated_at) - Order:订单(order_no, user, total_amount, status, address, receiver, phone, remark, created_at, updated_at) - OrderItem:订单项(order, goods, price, quantity) 请为每个 Model 生成对应的 Django Admin 配置(admin.py),要求: 1. 使用 @admin.register 装饰器写法 2. list_display 要包含所有关键字段 3. 每个 Admin 类要有 list_filter、search_fields 4. Goods 的 status 和 stock 字段设置 list_editable 5. Order 里用 inlines 把 OrderItem 内联进去 6. Order 添加两个自定义 action:mark_shipped 和 mark_cancelled 7. 只读字段要设置正确(created_at, updated_at, order_no 等) 8. 加上中文注释

AI 生成后的审查清单(别直接复制就用,花 2 分钟检查):

  1. 字段名是否正确:AI 可能猜错字段名,比如description写成desc。
  2. 外键字段双下划线:search_fields里用user__username这种写法。
  3. list_editable是否合法:里面的字段必须也在list_display里,否则报错。
  4. readonly_fields是否合理:created_at这种自动生成的一定要放进 readonly。

记住:AI 负责生成,你负责审查。这是 2026 年 Vibe Coding 的核心工作流。

懒人写法(但不推荐):

admin.site.register([Category,Goods,Order,OrderItem])

这样能用但只能用默认配置,享受不到list_display、search_fields这些优化。


安全加固:不让后台裸奔

功能做完了,最后一步——安全。

很多新手做完 Admin 直接上线,不管安全。开发环境没问题,但上了生产,后台就是黑客最爱的入口。

我见过太多案例:默认/admin/路径被扫描工具扫到,暴力破解密码,几分钟就攻破。这不是危言耸听,是真实发生的事。

下面几步加固措施成本全是 0,能挡住 95% 的常见攻击,建议上生产前全部做完。

改默认后台路径

默认/admin/太好猜了,改成一个没人知道的路径:

# settings.pyADMIN_URL="mall-admin-console-2026/"
# urls.pyfromdjango.urlsimportpathfromdjango.contribimportadminfromconfigimportsettings urlpatterns=[path(settings.ADMIN_URL,admin.site.urls),# 不再用 /admin/]

为什么重要?互联网上到处都是自动化扫描工具,专门扫/admin/、/wp-admin/这种默认路径。扫到就被列入暴力破解队列。改了路径,第一道门槛就挡住了。

小技巧:路径不要太有规律。/mall-admin-console-2026/比/admin2/好得多,后者太容易猜。建议用随机字符串,比如mall-admin-a3f8b2/。

限制访问 IP

只允许公司 IP 访问后台,用 IP 白名单中间件(核心逻辑):

# config/middleware.pyfromdjango.httpimportHttpResponseForbiddenfromdjango.confimportsettingsclassIPWhitelistMiddleware:"""只允许白名单 IP 访问后台"""def__init__(self,get_response):self.get_response=get_response self.admin_ips=getattr(settings,"ADMIN_ALLOWED_IPS",[])self.admin_prefix=getattr(settings,"ADMIN_URL","/admin/")def__call__(self,request):ifrequest.path.startswith(self.admin_prefix):client_ip=self._get_client_ip(request)ifself.admin_ipsandclient_ipnotinself.admin_ips:returnHttpResponseForbidden("Access Denied: IP not allowed")returnself.get_response(request)@staticmethoddef_get_client_ip(request):x_forwarded_for=request.META.get("HTTP_X_FORWARDED_FOR")ifx_forwarded_for:returnx_forwarded_for.split(",")[0].strip()returnrequest.META.get("REMOTE_ADDR")
# settings.pyMIDDLEWARE=[# ... 其他中间件 ..."config.middleware.IPWhitelistMiddleware",# 放在 CommonMiddleware 之后]ADMIN_ALLOWED_IPS=["127.0.0.1",# 本地开发"101.132.xx.xx",# 公司服务器出口 IP]

重要提示:修改前先确认你的 IP 不会变!动态 IP 建议用域名或 VPN 做白名单,避免把自己锁在外面。

防暴力破解:django-axes

Django Admin 默认登录页就是简单表单,容易被暴力破解。装个 django-axes:

pipinstalldjango-axes
# settings.pyINSTALLED_APPS=[# ..."axes",]MIDDLEWARE=[# ..."axes.middleware.AxesMiddleware",# 放在 SessionMiddleware 之后]AXES_FAILURE_LIMIT=5# 5 次失败AXES_COOLOFF_TIME=0.5# 封禁 30 分钟(0.5 小时)AXES_LOCK_OUT_BY_IP_AND_USER_AGENT=True

换掉默认超级管理员 + 强密码

默认admin用户名太常见,创建时换一个:

python manage.py shell>>>from mall.modelsimportCustomUser>>>user=CustomUser.objects.create_superuser(...username="meiyada_root_2026",# 换成随机字符串...email="root@meiyada.com",...password="强密码!包含特殊符号"...)

密码策略:至少 12 位,大小写 + 数字 + 特殊符号,不用生日手机号。

生产环境关闭 DEBUG

# settings.pyDEBUG=False# 生产环境必须改ALLOWED_HOSTS=["yourdomain.com","www.yourdomain.com"]

Debug 模式下,任何报错都会完整显示在浏览器里——文件路径、数据库配置、第三方密钥,等于把系统底牌全亮了。

安全加固总结清单

序号加固措施防御目标难度
1修改默认后台路径防扫描工具发现后台★☆☆
2IP 白名单限制只有授权 IP 可访问★★☆
3django-axes 防暴力破解防止密码暴力破解★☆☆
4自定义超级管理员用户名防止默认 admin 账号被猜★☆☆
5强密码策略防止弱口令攻击★☆☆
6关闭 DEBUG 模式防止敏感信息泄露★☆☆
7生产环境使用 HTTPS防止中间人攻击★★☆

以上 7 项全部做完,后台安全性至少能应付 90% 的常见攻击。


光看不动手,等于没学

改造题 1:给商品加「批量上下架」

仿照OrderAdmin的mark_shipped/mark_cancelled,给GoodsAdmin加两个 action:mark_online(批量上架 status=1)、mark_offline(批量下架 status=0)。

改造题 2:给用户加「批量禁用」

在CustomUserAdmin里加 actionbatch_deactivate,批量将选中用户的is_active设为False。

提示:参考OrderAdmin里mark_shipped的写法,字段名改成对应模型的即可。


Django Admin 官方文档见 docs.djangoproject.com。全篇成本 ¥0,到商城上线前一分钱不用花。

本系列为梅雅达编程笔记原创,首发于 CSDN。有问题?评论区见

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 4:40:09

Windows全平台离线更新工具:KB补丁/累积更新/驱动/.NET一键下载

简介:这是一款面向系统管理员、IT运维工程师及批量部署场景用户的Windows全平台离线更新下载工具,专为解决新装系统后需耗费数小时手动下载并安装海量补丁的痛点而设计。工具支持从Windows XP到8.1、Server 2003至2012 R2(含x86/x64&#xff…

作者头像 李华
网站建设 2026/10/12 4:40:06

C语言数组核心:从内存模型到指针纠缠,避开越界陷阱

(注意:输出内容为博文正文,从 ## 1. 开始,无前置说明,无结尾元信息)1. 数组不只是C语言的一道坎,更是理解指针和内存的钥匙很多学C语言的朋友都有这种感觉:数组的语法规则一节课就讲…

作者头像 李华
网站建设 2026/10/12 4:39:21

Vue项目在IE兼容下iframe传参对象丢失的根因与解决方案

接手过好几个在IE下崩掉的Vue后台项目,印象最深的是一个报表审核系统:父页面有一整套筛选条件对象,点“详情”要传给iframe子页面渲染。Chrome下一切正常,IE11下子页面打开总是提示“找不到对象属性”,排查半天发现传过…

作者头像 李华
网站建设 2026/10/12 4:39:07

GEO生成式引擎优化完全指南:从底层逻辑到实操框架

1. GEO行业框架的底层逻辑拆解1.1 GEO到底是什么,和SEO是什么关系GEO这个概念,全称是Generative Engine Optimization,中文一般叫"生成式引擎优化"。如果你之前做的是SEO,那理解GEO最快的方式就是:SEO优化的…

作者头像 李华
网站建设 2026/10/12 4:38:47

【dioxus0.7基础语法学与练】第3课:组件 Props 与组件通信

学习目标 本课解决两个问题:父组件如何向子组件传递数据,以及子组件如何向父组件回传消息。 知识点1:Props 基础 组件通过函数参数接收外部数据,#[component] 宏会自动把这些参数转为 Props 结构体。 use dioxus::prelude::*;// 定…

作者头像 李华