明白啦 ✅ 你想要的是:从不同层面(简单到复杂)自定义 Django Admin 的示例,直观展示有哪些扩展方式。下面我分层次给你整理:
1️⃣ 模型级别(ModelAdmin 自定义)
👉 最常见,改模型在后台的展示方式
# admin.py
from django.contrib import admin
from .models import Product
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ("id", "name", "price", "created_at") # 列表显示字段
search_fields = ("name",) # 搜索框
list_filter = ("category",) # 过滤器
ordering = ("-created_at",) # 默认排序
📌 适合:小改动(显示字段、过滤器、搜索)。
2️⃣ 操作级别(自定义动作)
👉 给列表页加按钮(批量执行任务)
# admin.py
@admin.action(description="批量打折 10%")
def apply_discount(modeladmin, request, queryset):
for product in queryset:
product.price *= 0.9
product.save()
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ("name", "price")
actions = [apply_discount]
📌 适合:批量操作,如导出、状态修改。
3️⃣ 模板级别(覆盖模板)
👉 修改后台页面样式/布局
目录结构:
templates/
└── admin/
└── base_site.html
base_site.html:
{% extends "admin/base.html" %}
{% block title %}我的管理后台{% endblock %}
{% block branding %}
<h1 id="site-name">数据平台后台</h1>
{% endblock %}
📌 适合:统一品牌风格(logo、标题)。
4️⃣ 站点级别(AdminSite 自定义)
👉 新建一个后台站点,区分不同角色
from django.contrib.admin import AdminSite
class ProductAdminSite(AdminSite):
site_header = "产品管理后台"
site_title = "产品后台"
index_title = "产品管理"
def has_permission(self, request):
return request.user.is_active and request.user.groups.filter(name="产品管理员").exists()
product_admin_site = ProductAdminSite(name="product_admin")
urls.py:
from django.urls import path
from .admin_sites import product_admin_site
urlpatterns = [
path("product_admin/", product_admin_site.urls),
]
📌 适合:需要多个后台入口(产品后台、运营后台)。
5️⃣ 视图级别(AdminSite 添加自定义页面)
👉 给后台加一个功能页(比如“执行任务”)
from django.urls import path
from django.template.response import TemplateResponse
class MyAdminSite(AdminSite):
def get_urls(self):
urls = super().get_urls()
my_urls = [
path("report/", self.admin_view(self.report_view), name="report"),
]
return my_urls + urls
def report_view(self, request):
context = dict(self.each_context(request), report="这里是报表数据")
return TemplateResponse(request, "admin/report.html", context)
📌 适合:加统计报表、系统任务、工具页面。
6️⃣ 应用级别(AdminConfig)
👉 替换全局后台,更模块化
# myapp/apps.py
from django.contrib.admin.apps import AdminConfig
class CustomAdminConfig(AdminConfig):
default_site = "myapp.admin.CustomAdminSite"
settings.py:
INSTALLED_APPS = [
"myapp.apps.CustomAdminConfig",
...
]
📌 适合:大项目需要 统一后台风格,并在多个 app 里复用。
🎯 总结
- ModelAdmin → 列表展示、字段定制
- Actions → 自定义批量操作
- Templates → 改 UI、换 logo
- AdminSite → 多后台、权限隔离
- 自定义视图 → 报表、工具页
- AdminConfig → 全局替换后台
要不要我给你画一个 层次金字塔图(从 ModelAdmin → AdminSite → AdminConfig),直观显示“自定义范围越来越大”的关系?
好 👍 我来帮你画一个 完整的 Django Admin 自定义字符图,把所有层次、关系和关键点都罗列出来,涵盖从最基础到高级(包括自定义 view):
┌───────────────────────────────────────┐
│ Django Admin │
└───────────────────┬───────────────────┘
│
┌────────────────┴─────────────────┐
│ │
基础配置 模型展示定制
│ │
▼ ▼
- 修改站点标题/页脚/LOGO - list_display
- site_header / site_title - list_display_links
- index_title - list_filter
- search_fields
- ordering
- readonly_fields
- fields / fieldsets
┌───────────────────────────────────────┐
│ 表单与字段定制 │
└───────────────────┬───────────────────┘
│
▼
- 自定义 ModelForm (form=...)
- formfield_overrides (全局字段样式)
- get_form() 动态修改
- clean_xxx() 校验逻辑
- raw_id_fields / autocomplete_fields
- 自定义小部件 widgets
- Inline (TabularInline / StackedInline) 内联表单
┌───────────────────────────────────────┐
│ 行为逻辑扩展 │
└───────────────────┬───────────────────┘
│
▼
- 自定义 action (批量操作按钮)
- save_model() / delete_model() 钩子
- get_queryset() 数据范围控制
- has_add/change/delete/view_permission 权限控制
- 自定义按钮(changelist_view + extra_context)
┌───────────────────────────────────────┐
│ 界面与前端扩展 │
└───────────────────┬───────────────────┘
│
▼
- 重写模板 base_site.html / change_list.html
- Media(css/js) 注入自定义样式和交互
- 自定义 AdminSite.index() 改首页布局
- 使用第三方主题 (django-grappelli, simpleui)
- dashboard 统计大屏扩展
┌───────────────────────────────────────┐
│ 自定义视图扩展 │
└───────────────────┬───────────────────┘
│
┌─────────────┴──────────────┐
│ │
ModelAdmin 级别 AdminSite 级别
│ │
▼ ▼
- get_urls() 增加子路由 - AdminSite.get_urls() 增加全局路由
- admin_view() 权限保护 - admin_view() 权限保护
- 自定义页面 (render/JsonResponse) - 独立页面(如 dashboard、报表)
- 常见场景:执行任务按钮、导出 - 全局统计、系统配置入口
📌 总结:
- 基础配置 → 修改后台站点的标题、LOGO、首页标题。
- 模型展示定制 → 控制列表页、字段显示、搜索、过滤。
- 表单与字段定制 → 定制表单行为、字段样式、内联表单。
- 行为逻辑扩展 → action、自定义权限、保存/删除逻辑。
- 界面与前端扩展 → 模板、样式、Dashboard、美化主题。
- 自定义视图扩展 → 在 ModelAdmin / AdminSite 下新增 URL 和自定义页面。
这样整个 Django Admin 的扩展点一览无余。
要不要我帮你把这个字符图配上 最小可运行的代码示例合集(每一层一个示例,拼成一个 Admin 自定义宝典)?
好的 ✅ 我给你整理一个 AdminSite 级别自定义的完整示例。
默认情况下我们用的是 django.contrib.admin.site
,如果要扩展,就要自己继承 AdminSite
。
1. 自定义 AdminSite
# myadmin.py
from django.contrib.admin import AdminSite
from django.urls import path
from django.http import HttpResponse
from django.utils.translation import gettext_lazy as _
class MyAdminSite(AdminSite):
# 基础配置
site_header = "数据平台管理后台"
site_title = "数据平台"
index_title = "欢迎进入数据平台后台"
# 扩展全局自定义 URL
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path("dashboard/", self.admin_view(self.dashboard_view)),
path("system-status/", self.admin_view(self.system_status)),
]
return custom_urls + urls
# 自定义视图1:Dashboard
def dashboard_view(self, request):
return HttpResponse("<h1>这是自定义 Dashboard 页面</h1>")
# 自定义视图2:系统状态
def system_status(self, request):
return HttpResponse("系统运行正常 ✅")
2. 在 urls.py
中使用
# urls.py
from django.urls import path, include
from .myadmin import MyAdminSite
from myapp.models import Book
from django.contrib import admin
# 注册模型
my_admin_site = MyAdminSite(name="myadmin")
my_admin_site.register(Book) # 注册模型到自定义后台
urlpatterns = [
path("myadmin/", my_admin_site.urls), # 使用自定义 AdminSite
path("admin/", admin.site.urls), # 默认 admin 仍然可用(可选)
]
3. 效果
/myadmin/
进入自定义后台,标题/页脚都改了/myadmin/dashboard/
访问自定义 Dashboard 页面/myadmin/system-status/
访问系统状态页面
4. 扩展方向
在 AdminSite
级别,你可以做的事情比 ModelAdmin
更全局:
- 全局 Dashboard(例如展示平台指标、统计图表)
- 全局工具入口(比如“系统配置”、“批量导入数据”)
- 替代默认
/admin/
,做成企业级后台
要不要我给你写一个 自定义 AdminSite Dashboard 页面(带模板 + 图表) 的完整示例?这样更接近实战场景。
明白了 ✅ 我帮你整理一个 AdminSite 级别视图 vs ModelAdmin 级别视图自定义的对比,包括关键点、用途、代码示例和适用场景。
1️⃣ 概念区别
特性 | AdminSite 级别视图 | ModelAdmin 级别视图 |
---|---|---|
作用范围 | 整个后台,全局路由 | 某个模型下的子页面或操作 |
URL 路径 | /myadmin/... ,可独立访问 | /myadmin/modelname/... ,依赖模型上下文 |
注册方式 | 继承 AdminSite → get_urls() | 继承 ModelAdmin → get_urls() |
权限控制 | admin_view() 保护全局权限 | admin_view() + has_permission() /has_change_permission() |
典型用途 | Dashboard、报表、系统工具、全局配置 | 模型相关操作、批量任务、导出、状态变更 |
模板渲染 | 自定义模板 + each_context() | 自定义模板 + extra_context ,可继承模型上下文 |
依赖模型 | 可不依赖任何模型 | 必须依赖一个模型,或模型实例 |
2️⃣ 代码示例对比
A. AdminSite 级别视图
# myadmin.py
from django.contrib.admin import AdminSite
from django.urls import path
from django.shortcuts import render
class MyAdminSite(AdminSite):
site_header = "企业后台"
site_title = "企业管理"
index_title = "后台首页"
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path("dashboard/", self.admin_view(self.dashboard))
]
return custom_urls + urls
def dashboard(self, request):
context = dict(self.each_context(request))
context['message'] = "欢迎来到后台 Dashboard"
return render(request, "admin/dashboard.html", context)
# urls.py
my_admin_site = MyAdminSite(name="myadmin")
- 访问路径:
/myadmin/dashboard/
- 特点:全局页面,不依赖模型,可展示全平台统计或系统工具。
B. ModelAdmin 级别视图
from django.contrib import admin
from django.urls import path
from django.shortcuts import render
from .models import Task
class TaskAdmin(admin.ModelAdmin):
list_display = ("name", "status")
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path("<int:task_id>/run/", self.admin_site.admin_view(self.run_task))
]
return custom_urls + urls
def run_task(self, request, task_id):
task = Task.objects.get(id=task_id)
# 执行自定义逻辑
context = dict(
self.admin_site.each_context(request),
task=task,
result="任务已执行"
)
return render(request, "admin/run_task.html", context)
admin.site.register(Task, TaskAdmin)
- 访问路径:
/admin/app/task/123/run/
- 特点:绑定模型,通常用于操作模型数据或批量操作。
3️⃣ 使用场景总结
层级 | 适合做什么 | 优势 | 局限 |
---|---|---|---|
AdminSite | Dashboard、全局统计、系统管理工具、企业级入口 | 全局控制、可不依赖模型 | 不方便绑定单模型操作 |
ModelAdmin | 模型相关操作(批量处理、导出、状态变更) | 依赖模型上下文,可直接操作模型实例 | 只能在模型下访问,影响范围有限 |
如果你愿意,我可以帮你画一个 AdminSite vs ModelAdmin 自定义视图的字符图,把两者的关系和路径层次可视化,方便快速理解。
你想要我画吗?
明白了 ✅ 我帮你整理一个 AdminSite 级别视图 vs ModelAdmin 级别视图自定义的对比,包括关键点、用途、代码示例和适用场景。
1️⃣ 概念区别
特性 | AdminSite 级别视图 | ModelAdmin 级别视图 |
---|---|---|
作用范围 | 整个后台,全局路由 | 某个模型下的子页面或操作 |
URL 路径 | /myadmin/... ,可独立访问 | /myadmin/modelname/... ,依赖模型上下文 |
注册方式 | 继承 AdminSite → get_urls() | 继承 ModelAdmin → get_urls() |
权限控制 | admin_view() 保护全局权限 | admin_view() + has_permission() /has_change_permission() |
典型用途 | Dashboard、报表、系统工具、全局配置 | 模型相关操作、批量任务、导出、状态变更 |
模板渲染 | 自定义模板 + each_context() | 自定义模板 + extra_context ,可继承模型上下文 |
依赖模型 | 可不依赖任何模型 | 必须依赖一个模型,或模型实例 |
2️⃣ 代码示例对比
A. AdminSite 级别视图
# myadmin.py
from django.contrib.admin import AdminSite
from django.urls import path
from django.shortcuts import render
class MyAdminSite(AdminSite):
site_header = "企业后台"
site_title = "企业管理"
index_title = "后台首页"
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path("dashboard/", self.admin_view(self.dashboard))
]
return custom_urls + urls
def dashboard(self, request):
context = dict(self.each_context(request))
context['message'] = "欢迎来到后台 Dashboard"
return render(request, "admin/dashboard.html", context)
# urls.py
my_admin_site = MyAdminSite(name="myadmin")
- 访问路径:
/myadmin/dashboard/
- 特点:全局页面,不依赖模型,可展示全平台统计或系统工具。
B. ModelAdmin 级别视图
from django.contrib import admin
from django.urls import path
from django.shortcuts import render
from .models import Task
class TaskAdmin(admin.ModelAdmin):
list_display = ("name", "status")
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path("<int:task_id>/run/", self.admin_site.admin_view(self.run_task))
]
return custom_urls + urls
def run_task(self, request, task_id):
task = Task.objects.get(id=task_id)
# 执行自定义逻辑
context = dict(
self.admin_site.each_context(request),
task=task,
result="任务已执行"
)
return render(request, "admin/run_task.html", context)
admin.site.register(Task, TaskAdmin)
- 访问路径:
/admin/app/task/123/run/
- 特点:绑定模型,通常用于操作模型数据或批量操作。
3️⃣ 使用场景总结
层级 | 适合做什么 | 优势 | 局限 |
---|---|---|---|
AdminSite | Dashboard、全局统计、系统管理工具、企业级入口 | 全局控制、可不依赖模型 | 不方便绑定单模型操作 |
ModelAdmin | 模型相关操作(批量处理、导出、状态变更) | 依赖模型上下文,可直接操作模型实例 | 只能在模型下访问,影响范围有限 |
如果你愿意,我可以帮你画一个 AdminSite vs ModelAdmin 自定义视图的字符图,把两者的关系和路径层次可视化,方便快速理解。
你想要我画吗?