Components API 参考¶
组件是 Django Admin Dashboards 中数据看板的构建块。本参考涵盖所有组件类、其属性、方法和使用模式。
目录¶
概述¶
什么是组件?¶
组件是表示数据看板上视觉元素的Python类:
- 自包含: 每个组件管理自己的数据和渲染
- 可配置: 属性控制外观和行为
- 基于模板: HTML模板定义视觉呈现
- 上下文感知: 能适应请求上下文和用户
组件类型¶
| 组件 | 描述 | 使用场景 |
|---|---|---|
CardComponent |
显示带有图标、值和趋势的指标 | 指标、统计、关键指标 |
ChartComponent |
使用图表.js进行数据可视化 | 趋势、比较、分布 |
TableComponent |
表格数据展示 | 列表、网格、详细数据 |
FilterComponent |
交互式过滤控件 | 数据过滤、参数选择 |
| 自定义组件 | 用户定义的组件 | 专用可视化 |
导入路径¶
from django_admin_dashboards.base import (
Component,
CardComponent,
ChartComponent,
TableComponent,
FilterComponent
)
组件基类¶
Component 类¶
class Component:
"""基础组件类"""
component_type = None
template_name = None
def __init__(self, **kwargs):
"""使用关键字参数初始化组件"""
def get_context_data(self, request):
"""获取组件渲染的上下文数据"""
def render(self, request):
"""将组件渲染为HTML"""
属性¶
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
component_type |
str |
None |
组件类型标识符 |
template_name |
str |
None |
渲染模板路径 |
方法¶
__init__(**kwargs)¶
参数:
**kwargs: 组件属性作为关键字参数
描述:
初始化组件实例。所有关键字参数都设置为实例属性。
使用:
component = Component(title="My Component", value=100)
print(component.title) # "My Component"
print(component.value) # 100
get_context_data(request)¶
参数:
request(Django.http.HttpRequest): 当前HTTP请求
返回:
dict - 模板上下文字典
描述:
准备模板渲染的上下文数据。基类实现返回最小上下文。
默认上下文:
重写示例:
def get_context_data(self, request):
context = super().get_context_data(request)
context["custom_data"] = self.calculate_data()
context["user"] = request.user
return context
render(request)¶
参数:
request(Django.http.HttpRequest): 当前HTTP请求
返回: str - HTML字符串(基础实现)
描述:
将组件渲染为HTML。实际上,组件通过Django模板渲染。
注意: 仅在特殊情况下重写;通常使用模板渲染。
卡片组件¶
概述¶
显示关键绩效指标 (KPIs),支持多值、趋势和图标。
class CardComponent(Component):
"""Card component for displaying metrics"""
component_type = "card"
template_name = "admin/components/card.html"
def __init__(
self,
title,
value=None,
change=None,
trend=None,
color="primary",
icon_class=None,
values=None,
value_labels=None,
**kwargs
):
# ... initialization
构造函数参数¶
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
title |
str |
必需 | 卡片标题 |
value |
any |
None |
主值(向后兼容) |
change |
str |
None |
变化指示器(例如 "+5%") |
trend |
str |
None |
趋势方向("up", "down", "neutral") |
color |
str |
"primary" |
颜色主题: "primary", "success", "warning", "danger", "info" |
icon_class |
str |
"ri-bar-chart-2-line" |
RemixIcon CSS类 |
values |
list |
None |
用于显示的多值 |
value_labels |
list |
[] |
多值标签 |
link |
str |
None |
单个值的链接URL |
links |
list |
[] |
多值对应的链接URL列表 |
**kwargs |
any |
- | 额外组件属性 |
属性¶
| 属性 | 类型 | 描述 |
|---|---|---|
title |
str |
卡片标题 |
value |
any |
主值 |
change |
str |
变化指示器 |
trend |
str |
趋势方向 |
color |
str |
颜色主题 |
icon_class |
str |
图标CSS类 |
values |
list |
多值 |
value_labels |
list |
值标签 |
link |
str |
单个值的链接URL |
links |
list |
多值对应的链接URL列表 |
使用 示例¶
基础 卡片¶
card = CardComponent(
title="Total Users",
value=150,
change="+5%",
trend="up",
color="primary",
icon_class="ri-user-line"
)
Multi-value 卡片¶
card = CardComponent(
title="User Status",
values=[100, 25, 125], # Active, Inactive, Total
value_labels=["Active", "Inactive", "Total"],
color="info",
icon_class="ri-user-2-line"
)
Status 卡片¶
card = CardComponent(
title="System Status",
value="Online",
change="✓",
trend="up",
color="success",
icon_class="ri-server-line"
)
warning 卡片¶
card = CardComponent(
title="Storage Usage",
value="85%",
change="+10%",
trend="down", # Down is bad for storage usage
color="warning",
icon_class="ri-hard-drive-line"
)
带链接的卡片¶
# 单个值带链接
card = CardComponent(
title="Total Users",
value=150,
link="/admin/auth/user/", # 点击数字跳转到用户列表
color="primary",
icon_class="ri-user-line"
)
# 多值带链接
card = CardComponent(
title="User Status",
values=[100, 25, 125], # Active, Inactive, Total
value_labels=["Active", "Inactive", "Total"],
links=[
"/admin/auth/user/?is_active__exact=1",
"/admin/auth/user/?is_active__exact=0",
"/admin/auth/user/"
],
color="info",
icon_class="ri-user-2-line"
)
Template Context¶
卡片 components provide the following template context:
{
"component": self,
"component_type": "card",
"title": self.title,
"value": self.value,
"change": self.change,
"trend": self.trend,
"color": self.color,
"icon_class": self.icon_class,
"values": self.values,
"value_labels": self.value_labels,
"link": self.link,
"links": self.links,
"has_multiple_values": len(self.values) > 1,
"value_pairs": list(zip(self.values, self.value_labels)),
}
Color Themes¶
Available color themes and their CSS classes:
| Color | CSS Class | Typical Use |
|---|---|---|
primary |
卡片-primary |
Primary metrics |
success |
卡片-success |
Positive indicators |
warning |
卡片-warning |
Caution/Warning |
danger |
卡片-danger |
Critical issues |
info |
卡片-info |
Informational |
secondary |
卡片-secondary |
Secondary metrics |
Icon Classes¶
Use RemixIcon classes for icons:
# User-related icons
icon_class="ri-user-line"
icon_class="ri-user-2-line"
icon_class="ri-user-3-line"
# Chart icons
icon_class="ri-bar-chart-2-line"
icon_class="ri-line-chart-line"
icon_class="ri-pie-chart-2-line"
# System icons
icon_class="ri-server-line"
icon_class="ri-database-2-line"
icon_class="ri-cpu-line"
# Business icons
icon_class="ri-money-dollar-circle-line"
icon_class="ri-shopping-cart-2-line"
icon_class="ri-store-2-line"
图表组件¶
概述¶
创建 交互式 charts using 图表.js 库.
class ChartComponent(Component):
"""Chart component using Chart.js"""
component_type = "chart"
template_name = "admin/components/chart.html"
def __init__(self, title, chart_type, data, options=None, height=400, **kwargs):
# ... initialization
构造函数参数¶
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
title |
str |
必需 | 图表标题 |
chart_type |
str |
必需 | 图表类型: "line", "bar", "pie", "doughnut", "radar", "polarArea", "bubble", "scatter" |
data |
dict |
必需 | 图表.js 数据配置 |
options |
dict |
None |
图表.js选项 |
height |
int |
400 |
图表高度(像素) |
**kwargs |
any |
- | 额外组件属性 |
属性¶
| 属性 | 类型 | 描述 |
|---|---|---|
title |
str |
图表标题 |
chart_type |
str |
图表类型 |
data |
dict |
图表数据 |
options |
dict |
图表选项 |
height |
int |
图表高度 |
使用 示例¶
Line 图表¶
chart = ChartComponent(
title="User Growth",
chart_type="line",
data={
"labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
"datasets": [{
"label": "New Users",
"data": [12, 19, 3, 5, 2, 3],
"borderColor": "rgb(75, 192, 192)",
"tension": 0.1
}]
},
options={
"responsive": True,
"plugins": {
"legend": {
"position": "top",
},
"title": {
"display": True,
"text": "Monthly User Growth"
}
}
},
height=400
)
Bar 图表¶
chart = ChartComponent(
title="Monthly Sales",
chart_type="bar",
data={
"labels": ["Q1", "Q2", "Q3", "Q4"],
"datasets": [
{
"label": "2023",
"data": [65, 59, 80, 81],
"backgroundColor": "rgba(255, 99, 132, 0.5)",
},
{
"label": "2024",
"data": [28, 48, 40, 19],
"backgroundColor": "rgba(54, 162, 235, 0.5)",
}
]
}
)
Pie 图表¶
chart = ChartComponent(
title="User Distribution",
chart_type="pie",
data={
"labels": ["Active", "Inactive", "Suspended"],
"datasets": [{
"label": "Users",
"data": [300, 50, 100],
"backgroundColor": [
"rgb(255, 99, 132)",
"rgb(54, 162, 235)",
"rgb(255, 205, 86)"
],
}]
}
)
Template Context¶
图表 components provide the following template context:
{
"component": self,
"component_type": "chart",
"title": self.title,
"chart_type": self.chart_type,
"data_json": json.dumps(self.data),
"options_json": json.dumps(self.options or {}),
"chart_id": f"chart_{id(self)}", # Unique ID for DOM element
"height": self.height,
}
图表类型¶
支持的 Chart.js 图表类型:
| 类型 | 描述 | 使用场景 |
|---|---|---|
line |
折线图 | 时间趋势分析 |
bar |
柱状图 | 类别对比 |
pie |
饼图 | 整体比例 |
doughnut |
环形图 | 带空洞的比例 |
radar |
雷达图 | 多变量数据 |
polarArea |
极区图 | 比例角度 |
bubble |
气泡图 | 三维数据 |
scatter |
散点图 | 变量关系 |
图表类型详细说明¶
每种图表类型有其特定的数据结构和选项配置:
1. 折线图 (line)¶
用于展示数据随时间或其他连续变量的变化趋势。
数据格式示例:
data = {
"labels": ["1月", "2月", "3月", "4月", "5月", "6月"],
"datasets": [{
"label": "用户增长",
"data": [12, 19, 3, 5, 2, 3],
"borderColor": "rgb(75, 192, 192)",
"backgroundColor": "rgba(75, 192, 192, 0.1)",
"borderWidth": 2,
"tension": 0.4, # 曲线平滑度 (0=直线, 1=最平滑)
"fill": True # 是否填充区域
}]
}
常用选项:
options = {
"responsive": True,
"plugins": {
"legend": {"position": "top"},
"tooltip": {"mode": "index", "intersect": False}
},
"scales": {
"y": {
"beginAtZero": True,
"title": {"display": True, "text": "用户数"}
},
"x": {
"title": {"display": True, "text": "月份"}
}
}
}
2. 柱状图 (bar)¶
用于比较不同类别的数值大小。
数据格式示例:
data = {
"labels": ["第一季度", "第二季度", "第三季度", "第四季度"],
"datasets": [
{
"label": "2023年",
"data": [65, 59, 80, 81],
"backgroundColor": "rgba(255, 99, 132, 0.7)",
"borderColor": "rgb(255, 99, 132)",
"borderWidth": 1
},
{
"label": "2024年",
"data": [28, 48, 40, 19],
"backgroundColor": "rgba(54, 162, 235, 0.7)",
"borderColor": "rgb(54, 162, 235)",
"borderWidth": 1
}
]
}
水平柱状图配置:
options = {
"indexAxis": "y", # 水平柱状图
"responsive": True,
"plugins": {
"legend": {"position": "right"}
}
}
3. 饼图 (pie) 和环形图 (doughnut)¶
用于展示各部分占整体的比例。
数据格式示例:
data = {
"labels": ["启用用户", "禁用用户", "总计"],
"datasets": [{
"label": "用户分布",
"data": [300, 50, 100],
"backgroundColor": [
"rgb(255, 99, 132)",
"rgb(54, 162, 235)",
"rgb(255, 205, 86)"
],
"borderColor": "white",
"borderWidth": 2,
"hoverOffset": 15 # 悬停时偏移量
}]
}
环形图额外配置:
options = {
"cutout": "50%", # 环形图空洞大小(百分比)
"plugins": {
"legend": {"position": "bottom"},
"tooltip": {
"callbacks": {
"label": "function(context) { return context.label + ': ' + context.parsed + ' (' + context.percentage + '%)'; }"
}
}
}
}
4. 雷达图 (radar)¶
用于展示多变量数据,比较多个指标。
数据格式示例:
data = {
"labels": ["产品", "价格", "服务", "质量", "创新"],
"datasets": [
{
"label": "公司A",
"data": [65, 59, 90, 81, 56],
"backgroundColor": "rgba(255, 99, 132, 0.2)",
"borderColor": "rgb(255, 99, 132)",
"pointBackgroundColor": "rgb(255, 99, 132)"
},
{
"label": "公司B",
"data": [28, 48, 40, 19, 96],
"backgroundColor": "rgba(54, 162, 235, 0.2)",
"borderColor": "rgb(54, 162, 235)",
"pointBackgroundColor": "rgb(54, 162, 235)"
}
]
}
5. 极区图 (polarArea)¶
类似于饼图,但扇区角度代表数值比例。
数据格式示例:
data = {
"labels": ["红色", "蓝色", "黄色", "绿色", "紫色"],
"datasets": [{
"label": "颜色分布",
"data": [11, 16, 7, 3, 14],
"backgroundColor": [
"rgb(255, 99, 132)",
"rgb(54, 162, 235)",
"rgb(255, 205, 86)",
"rgb(75, 192, 192)",
"rgb(153, 102, 255)"
]
}]
}
6. 气泡图 (bubble)¶
用于展示三维数据(x, y, 半径)。
数据格式示例:
data = {
"datasets": [{
"label": "产品A",
"data": [
{"x": 20, "y": 30, "r": 15},
{"x": 40, "y": 10, "r": 10},
{"x": 30, "y": 20, "r": 25}
],
"backgroundColor": "rgb(255, 99, 132)"
}]
}
7. 散点图 (scatter)¶
用于展示两个变量之间的关系。
数据格式示例:
data = {
"datasets": [{
"label": "数据集1",
"data": [
{"x": -10, "y": 0},
{"x": 0, "y": 10},
{"x": 10, "y": 5},
{"x": 0.5, "y": 5.5}
],
"backgroundColor": "rgb(255, 99, 132)"
}]
}
数据格式¶
图表 数据 follows 图表.js format:
data = {
"labels": ["Label 1", "Label 2", "Label 3"], # X-axis labels
"datasets": [
{
"label": "Dataset 1",
"data": [10, 20, 30], # Y-axis values
"borderColor": "rgb(75, 192, 192)", # Line/border color
"backgroundColor": "rgba(75, 192, 192, 0.5)", # Fill color
# ... other Chart.js dataset properties
}
]
}
Options 配置¶
Common 图表.js options:
options = {
"responsive": True,
"maintainAspectRatio": False,
"plugins": {
"legend": {
"position": "top",
"labels": {
"color": "#333", # Legend text color
"font": {
"size": 12
}
}
},
"title": {
"display": True,
"text": "Chart Title",
"color": "#333",
"font": {
"size": 16,
"weight": "bold"
}
},
"tooltip": {
"enabled": True,
"mode": "index",
"intersect": False
}
},
"scales": {
"x": {
"grid": {
"display": True,
"color": "rgba(0, 0, 0, 0.1)"
},
"ticks": {
"color": "#666"
}
},
"y": {
"grid": {
"display": True,
"color": "rgba(0, 0, 0, 0.1)"
},
"ticks": {
"color": "#666"
}
}
}
}
深色模式 Support¶
Charts automatically adapt to 深色模式 when configured:
def get_context_data(self, request):
context = super().get_context_data(request)
# Adapt options for dark mode
if self.dashboard.is_dark_mode(request):
if not self.options:
self.options = {}
# Dark mode options
self.options.update({
"color": "#f9fafb", # Light text for dark mode
"plugins": {
"legend": {
"labels": {
"color": "#f9fafb"
}
}
},
"scales": {
"x": {
"grid": {
"color": "#374151"
},
"ticks": {
"color": "#9ca3af"
}
},
"y": {
"grid": {
"color": "#374151"
},
"ticks": {
"color": "#9ca3af"
}
}
}
})
return context
表格组件¶
概述¶
显示可定制列的表格数据。
class TableComponent(Component):
"""用于显示表格数据的表格组件"""
component_type = "table"
template_name = "admin/components/table.html"
def __init__(self, title, columns=None, data=None, **kwargs):
# ... initialization
构造函数参数¶
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
title |
str |
必需 | 表格标题 |
columns |
list |
[] |
列定义 |
data |
list |
[] |
行数据 |
**kwargs |
any |
- | 额外组件属性 |
列定义¶
列可以定义为字符串或字典:
# Simple column names
columns = ["ID", "Name", "Email", "Status"]
# Detailed column definitions
columns = [
{"name": "ID", "key": "id", "width": "50px"},
{"name": "Name", "key": "name", "sortable": True},
{"name": "Email", "key": "email", "type": "email"},
{"name": "Status", "key": "status", "type": "badge"},
]
数据格式¶
数据应为匹配列键的字典列表:
data = [
{"id": 1, "name": "John Doe", "email": "john@example.com", "status": "active"},
{"id": 2, "name": "Jane Smith", "email": "jane@example.com", "status": "inactive"},
# ... more rows
]
属性¶
| 属性 | 类型 | 描述 |
|---|---|---|
title |
str |
表格标题 |
columns |
list |
列定义 |
data |
list |
行数据 |
使用 示例¶
简单 表格¶
table = TableComponent(
title="Recent Users",
columns=["ID", "Username", "Email", "Date Joined"],
data=[
{"ID": 1, "Username": "john_doe", "Email": "john@example.com", "Date Joined": "2024-01-15"},
{"ID": 2, "Username": "jane_smith", "Email": "jane@example.com", "Date Joined": "2024-01-20"},
]
)
Detailed 表格 配置¶
table = TableComponent(
title="User Management",
columns=[
{"name": "ID", "key": "id", "width": "80px", "align": "center"},
{"name": "Username", "key": "username", "sortable": True, "searchable": True},
{"name": "Email", "key": "email", "type": "email", "truncate": True},
{"name": "Status", "key": "status", "type": "badge", "badge_colors": {
"active": "success",
"inactive": "secondary",
"suspended": "danger"
}},
{"name": "Actions", "key": "actions", "type": "actions", "actions": [
{"name": "Edit", "url": "/admin/auth/user/{id}/change/"},
{"name": "Delete", "url": "/admin/auth/user/{id}/delete/", "confirm": True}
]}
],
data=[
{
"id": 1,
"username": "admin",
"email": "admin@example.com",
"status": "active",
"actions": {"id": 1}
},
# ... more rows
]
)
动态 表格 数据¶
class UserTableComponent(TableComponent):
def get_context_data(self, request):
context = super().get_context_data(request)
# Fetch data dynamically
users = User.objects.all().order_by('-date_joined')[:10]
# Format data
context["data"] = [
{
"id": user.id,
"username": user.username,
"email": user.email,
"status": "active" if user.is_active else "inactive",
"date_joined": user.date_joined.strftime("%Y-%m-%d %H:%M"),
"last_login": user.last_login.strftime("%Y-%m-%d %H:%M") if user.last_login else "Never"
}
for user in users
]
return context
Template Context¶
表格 components provide the following template context:
{
"component": self,
"component_type": "table",
"title": self.title,
"columns": self.columns,
"data": self.data,
"table_id": f"table_{id(self)}", # Unique ID for DOM element
"has_data": len(self.data) > 0,
"row_count": len(self.data),
"column_count": len(self.columns),
}
列 Types¶
Supported 列 types and their rendering:
| 类型 | 描述 | 示例 |
|---|---|---|
text |
Plain text (默认) | {"type": "text"} |
email |
Email link | {"type": "email"} |
URL |
URL link | {"type": "URL"} |
badge |
Colored badge | {"type": "badge"} |
boolean |
Yes/No or checkmark | {"type": "boolean"} |
date |
Formatted date | {"type": "date"} |
datetime |
Formatted datetime | {"type": "datetime"} |
number |
Formatted number | {"type": "number"} |
actions |
Action buttons | {"type": "actions"} |
列 Options¶
Common 列 配置 options:
column = {
"name": "Column Name", # Display name
"key": "field_name", # Data key
"type": "text", # Column type
"width": "100px", # Fixed width
"align": "left", # Text alignment: left, center, right
"sortable": True, # Enable sorting
"searchable": True, # Enable searching
"truncate": True, # Truncate long text
"max_length": 50, # Max length for truncation
"format": "{:.2f}", # Format string for numbers
"date_format": "%Y-%m-%d", # Date format
"badge_colors": { # Color mapping for badges
"active": "success",
"inactive": "warning"
},
"actions": [ # Actions for action type
{"name": "Edit", "url": "/edit/{id}/"},
{"name": "Delete", "url": "/delete/{id}/", "confirm": True}
]
}
深色模式 Support¶
Tables automatically adapt to 深色模式:
/* Table dark mode styles in dashboard.css */
[data-theme="dark"] .dashboard table {
background-color: #111827;
color: #f9fafb;
border-color: #374151;
}
[data-theme="dark"] .dashboard table thead {
background-color: #1f2937;
border-bottom-color: #374151;
}
[data-theme="dark"] .dashboard table th {
color: #d1d5db;
}
[data-theme="dark"] .dashboard table tr:hover {
background-color: #1f2937;
}
过滤器组件¶
概述¶
创建交互式过滤器控件,支持多种过滤器类型和现代化的下拉面板界面。
主要特性: - 下拉面板设计:过滤器隐藏在触发按钮后的下拉面板中,节省空间 - 多种过滤器类型:支持单选、多选、日期范围、数值范围、文本、数字、复选框等 - Select2集成:所有选择框使用Select2组件,支持搜索功能 - 响应式布局:自适应桌面和移动设备 - 过滤器计数:显示当前应用的过滤器数量 - 浅色UI设计:与Django Admin界面协调的浅灰色按钮样式
class FilterComponent(Component):
"""过滤器组件"""
component_type = "filter"
template_name = "admin/components/filter.html"
def __init__(self, title, filters=None, **kwargs):
super().__init__(**kwargs)
self.title = title
self.filters = filters or []
def get_context_data(self, request):
"""获取过滤器组件的上下文数据"""
context = super().get_context_data(request)
context.update({
"filter_id": f"filter_{id(self)}",
"filters": self.filters,
})
return context
构造函数参数¶
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
title |
str |
必需 | 过滤器区域标题 |
filters |
list |
[] |
过滤器定义 |
**kwargs |
any |
- | 额外组件属性 |
过滤器定义¶
过滤器定义为字典列表,支持以下类型:select、multi_select、date_range、text、number、number_range、checkbox。
通用字段:
- name: 过滤器字段名称(表单字段名)
- label: 显示标签
- type: 过滤器类型
- default: 默认值(可选)
不同类型特有字段:
select 类型:
- options: 选项列表,每个选项为 {"value": "...", "label": "..."} 字典
- default: 默认选中的值
- 使用 Select2 组件,支持搜索功能
multi_select 类型:
- options: 选项列表,每个选项为 {"value": "...", "label": "..."} 字典
- default: 默认选中的值列表(数组)
- 使用 Select2 多选组件,支持搜索和标签显示
- 提交时使用数组参数 name="field_name[]"
date_range 类型:
- default: 默认日期范围,可选值:all_time、today、yesterday、last_7_days、last_30_days、this_month、last_month、this_year、last_year、custom
- all_time: 表示不应用日期过滤,显示所有时间的数据
- 当选择 custom 时,会显示自定义日期输入框
text 类型:
- default: 默认文本值(可选)
- placeholder: 占位符文本(可选)
number 类型:
- default: 默认数值(可选)
number_range 类型:
- min_value: 最小值(可选)
- max_value: 最大值(可选)
- 提供两个输入框分别输入最小值和最大值
- 支持HTML5 number输入类型
checkbox 类型:
- options: 复选框选项列表,每个选项为 {"value": "...", "label": "..."} 字典
- default: 默认选中的值列表(数组)
filters = [
{
"name": "status",
"label": "状态",
"type": "select",
"options": [
{"value": "all", "label": "全部"},
{"value": "active", "label": "启用"},
{"value": "inactive", "label": "禁用"}
],
"default": "all"
},
{
"name": "tags",
"label": "标签",
"type": "multi_select",
"options": [
{"value": "featured", "label": "精选"},
{"value": "new", "label": "新品"},
{"value": "sale", "label": "促销"},
{"value": "bestseller", "label": "畅销"}
],
"default": []
},
{
"name": "date_range",
"label": "日期范围",
"type": "date_range",
"default": "last_30_days"
},
{
"name": "amount_range",
"label": "金额范围",
"type": "number_range",
"min_value": 0,
"max_value": 10000
},
{
"name": "search",
"label": "搜索",
"type": "text",
"placeholder": "输入关键词..."
},
# ... 更多过滤器
]
属性¶
| 属性 | 类型 | 描述 |
|---|---|---|
title |
str |
过滤器 title |
filters |
list |
过滤器 definitions |
使用 示例¶
基础过滤器¶
filter_component = FilterComponent(
title="用户过滤器",
filters=[
{
"name": "status",
"label": "用户状态",
"type": "select",
"options": [
{"value": "all", "label": "全部用户"},
{"value": "active", "label": "仅启用用户"},
{"value": "inactive", "label": "仅禁用用户"}
],
"default": "all"
},
{
"name": "role",
"label": "用户角色",
"type": "select",
"options": [
{"value": "all", "label": "全部角色"},
{"value": "admin", "label": "管理员"},
{"value": "user", "label": "普通用户"}
],
"default": "all"
},
{
"name": "search",
"label": "搜索",
"type": "text",
"placeholder": "按姓名或邮箱搜索..."
}
]
)
日期范围过滤器¶
filter_component = FilterComponent(
title="日期过滤器",
filters=[
{
"name": "date_range",
"label": "日期范围",
"type": "date_range",
"default": "last_30_days"
}
]
)
多种过滤器类型示例¶
filter_component = FilterComponent(
title="综合过滤器",
filters=[
{
"name": "category",
"label": "分类",
"type": "select",
"options": [
{"value": "all", "label": "全部分类"},
{"value": "tech", "label": "技术"},
{"value": "business", "label": "商业"},
{"value": "science", "label": "科学"}
],
"default": "all"
},
{
"name": "price_range",
"label": "价格范围",
"type": "number",
"default": 100
},
{
"name": "tags",
"label": "标签",
"type": "checkbox",
"options": [
{"value": "new", "label": "新品"},
{"value": "popular", "label": "热门"},
{"value": "featured", "label": "推荐"}
],
"default": ["new"]
},
{
"name": "date_range",
"label": "发布日期",
"type": "date_range",
"default": "this_month"
}
]
)
动态 过滤器 Options¶
class DynamicFilterComponent(FilterComponent):
def get_context_data(self, request):
context = super().get_context_data(request)
# Generate filter options dynamically
user_groups = Group.objects.all()
context["filters"] = [
{
"name": "group",
"label": "User Group",
"type": "select",
"options": [
{"value": "", "label": "All Groups"}
] + [
{"value": str(group.id), "label": group.name}
for group in user_groups
]
}
]
return context
Template Context¶
过滤器 components provide the following template context:
{
"component": self,
"component_type": "filter",
"title": self.title,
"filters": self.filters,
"filter_id": f"filter_{id(self)}", # Unique ID for DOM element
"has_filters": len(self.filters) > 0,
}
过滤器 Types¶
Supported 过滤器 types:
| 类型 | 描述 | HTML元素 |
|---|---|---|
text |
Text input | <input type="text"> |
select |
Dropdown select | <select> |
multiselect |
Multiple selection | <select multiple> |
checkbox |
Checkbox | <input type="checkbox"> |
radio |
Radio buttons | <input type="radio"> |
daterange |
Date range picker | Two date inputs |
date |
Single date picker | <input type="date"> |
number |
Number input | <input type="number"> |
range |
Range slider | <input type="range"> |
过滤器 Options¶
Common 过滤器 配置 options:
filter = {
"name": "field_name", # Query parameter name
"label": "Filter Label", # Display label
"type": "select", # Filter type
"options": [ # Options for select types
{"value": "", "label": "All"},
{"value": "option1", "label": "Option 1"}
],
"default": "", # Default value
"placeholder": "Type here...", # Placeholder for text inputs
"required": False, # Required field
"multiple": False, # Multiple selection for selects
"min": 0, # Minimum value for number/range
"max": 100, # Maximum value for number/range
"step": 1, # Step for number/range
"format": "YYYY-MM-DD", # Date format for date inputs
"ranges": { # Predefined ranges for daterange
"Today": [today, today],
"Last 7 Days": [today - timedelta(days=6), today]
}
}
JavaScript Integration¶
过滤器 components include JavaScript for interactivity:
// Filter component JavaScript
document.addEventListener('DOMContentLoaded', function() {
const filterForm = document.querySelector('.dashboard-filter-form');
if (filterForm) {
// Handle filter changes
filterForm.addEventListener('change', function() {
applyFilters();
});
// Handle filter submission
filterForm.addEventListener('submit', function(e) {
e.preventDefault();
applyFilters();
});
function applyFilters() {
const formData = new FormData(filterForm);
const params = new URLSearchParams();
// Build query parameters
for (const [key, value] of formData.entries()) {
if (value) {
params.append(key, value);
}
}
// Update URL without reload
const newUrl = window.location.pathname + '?' + params.toString();
window.history.pushState({}, '', newUrl);
// Dispatch filter change event
window.dispatchEvent(new CustomEvent('dashboardfilterchange', {
detail: { params: Object.fromEntries(params) }
}));
}
}
});
自定义组件¶
创建自定义组件¶
扩展基础 Component 类以创建自定义组件:
from django_admin_dashboards.base import Component
class CustomComponent(Component):
"""Custom component example"""
component_type = "custom"
template_name = "admin/components/custom.html"
def __init__(self, title, data=None, **kwargs):
super().__init__(**kwargs)
self.title = title
self.data = data or []
def get_context_data(self, request):
context = super().get_context_data(request)
# Add custom context
context.update({
"title": self.title,
"data": self.data,
"processed_data": self.process_data(),
"user": request.user if request else None,
})
return context
def process_data(self):
"""Process data for display"""
return [item.upper() for item in self.data]
Template for 自定义 组件¶
创建 a template at admin/components/自定义.HTML:
<div class="dashboard-component custom-component">
<div class="component-header">
<h3>{{ title }}</h3>
</div>
<div class="component-body">
{% if data %}
<ul>
{% for item in processed_data %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% else %}
<p class="text-muted">No data available</p>
{% endif %}
</div>
<div class="component-footer">
<small>Displaying {{ data|length }} items</small>
</div>
</div>
注册自定义组件¶
在数据看板中使用自定义组件:
from .components import CustomComponent
class MyDashboard(Dashboard):
def get_layout(self):
layout = Layout(columns=12)
custom = CustomComponent(
title="Custom Data",
data=["item1", "item2", "item3"]
)
layout.add_component(custom, width=12)
return layout
高级 自定义 组件¶
创建 components with 复杂 behavior:
class InteractiveChartComponent(Component):
"""Interactive chart with server-side data"""
component_type = "interactive_chart"
template_name = "admin/components/interactive_chart.html"
def __init__(self, title, endpoint, **kwargs):
super().__init__(**kwargs)
self.title = title
self.endpoint = endpoint
self.chart_type = kwargs.get('chart_type', 'line')
def get_context_data(self, request):
context = super().get_context_data(request)
# Add AJAX endpoint
context['endpoint'] = self.endpoint
# Add initial data if needed
if hasattr(self, 'get_initial_data'):
context['initial_data'] = self.get_initial_data(request)
# Add chart configuration
context['chart_config'] = {
'type': self.chart_type,
'options': {
'responsive': True,
'maintainAspectRatio': False,
}
}
return context
@classmethod
def handle_ajax_request(cls, request, component_id):
"""Handle AJAX data requests"""
# Parse component ID and parameters
params = request.GET
# Fetch data based on parameters
data = cls.fetch_data(params)
return JsonResponse(data)
组件生命周期¶
初始化¶
- 组件创建:
Component(**kwargs)构造函数被调用 - 属性设置: 所有关键字参数设置为实例属性
- 上下文准备: 模板上下文初始化
上下文构建¶
- 请求处理:
get_context_data(request)被调用 - 数据获取: 组件检索必要的数据
- 上下文增强: 根据需要添加额外上下文
模板渲染¶
- 模板选择:
template_name用于查找模板 - 上下文注入: 上下文字典传递给模板
- HTML生成: 模板渲染为HTML
数据看板 Integration¶
- 布局添加: 组件添加到数据看板布局
- 上下文合并: 数据看板合并组件上下文
- 渲染: 数据看板模板包含组件模板
最佳实践¶
1. 保持组件专注¶
# Good: Single responsibility
class UserCountCard(CardComponent):
"""Card showing user count"""
pass
# Avoid: Multiple responsibilities
class UserDashboardCard(Component):
"""Card showing user count, recent activity, and messages"""
pass
2. 使用描述性属性名称¶
# Good
card = CardComponent(
title="Monthly Revenue",
value=50000,
currency="USD",
trend="up"
)
# Avoid
card = CardComponent(
t="Rev",
v=50000,
c="USD",
tr="u"
)
3. 优雅处理缺失数据¶
def get_context_data(self, request):
context = super().get_context_data(request)
try:
context['data'] = self.fetch_data()
except (DatabaseError, ConnectionError) as e:
context['data'] = []
context['error'] = str(e)
context['has_error'] = True
return context
4. 优化数据获取¶
class OptimizedChartComponent(ChartComponent):
def get_context_data(self, request):
context = super().get_context_data(request)
# Cache data fetching
cache_key = f"chart_data_{self.chart_type}_{request.user.pk}"
data = cache.get(cache_key)
if not data:
data = self.fetch_expensive_data()
cache.set(cache_key, data, timeout=300) # 5 minutes
context['data'] = data
return context
5. 测试 Components¶
from django.test import TestCase
from django.test.client import RequestFactory
class ComponentTests(TestCase):
def test_card_component(self):
card = CardComponent(title="Test", value=100)
self.assertEqual(card.title, "Test")
self.assertEqual(card.value, 100)
def test_component_context(self):
factory = RequestFactory()
request = factory.get('/')
component = CardComponent(title="Test", value=100)
context = component.get_context_data(request)
self.assertIn('component', context)
self.assertIn('title', context)
6. 文档化组件使用¶
class DocumentedComponent(Component):
"""
用于显示用户统计信息的组件。
参数:
- title (str): 组件标题
- user_ids (list): 要包含的用户ID列表
- timeframe (str): 时间段:'day', 'week', 'month'
使用示例:
>>> component = DocumentedComponent(
... title="User Activity",
... user_ids=[1, 2, 3],
... timeframe="week"
... )
"""
def __init__(self, title, user_ids=None, timeframe='day', **kwargs):
super().__init__(**kwargs)
self.title = title
self.user_ids = user_ids or []
self.timeframe = timeframe
相关文档¶
- 数据看板 API - 数据看板类和配置
- 布局 API - 布局管理和组件排列
- 用户指南: Components - 实用组件使用指南
- 示例 - 真实世界组件示例