【Dv3Admin】Django动态配置首页仪表盘

主页动态配置模块常见风险集中在配置错配与越权展示,表现为菜单缺失、组件顺序异常、跨公司配置被误读入渲染链路。

内容围绕 Home 的 HomeMenu 模块拆解,聚焦 company 参数约束、查询过滤条件、setting_data 配置承载方式与返回链路。

文章目录

需求解析

模块归属信息来自 Django AppConfig,路由注册来自 DRF DefaultRouter。

项目 材料依据 说明
App 模块名 Home/apps.py modules.HengShenGroup.Home
路由注册 Home/urls.py 注册 WorkbenchesHomeMenu 两个前缀
配置存储 Home/models.py HomeMenu.setting_data 使用 JSONField
过滤入口 Home/views_app/HomeMenu.py get_queryset 基于登录态、company 参数、list 动作过滤

这里实现的是通过一套数据库管理,统一配置每个分公司/部门的可视化home面板,方便用户基于前端数据进行子女的一个调试。
数据筛选与返回
权限与范围约束
路由入口
进入模块路由
命中主页菜单入口
校验登录态
读取公司参数
校验公司范围
列表动作触发过滤
返回符合条件的数据集

功能实现

定位对象模块注册配置;目的说明:声明 Django 应用路径,保证模块可被加载。

python 复制代码
from django.apps import AppConfig


class HomeConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "modules.HengShenGroup.Home"

需要注意的是 name 直接决定模块在工程内的定位路径。

定位对象:路由注册;目的说明:通过 DefaultRouter 暴露 HomeMenu 相关入口。

python 复制代码
from rest_framework.routers import DefaultRouter
from dvadmin.utils.workbenches import WorkbenchesViewSet

from modules.HengShenGroup.Home.views_app.HomeMenu import HomeMenuViewSet

router = DefaultRouter()
router.register('Workbenches', WorkbenchesViewSet, 'Workbenches')
router.register('HomeMenu', HomeMenuViewSet, 'HomeMenu')

urlpatterns = [
    # url(r'AccountsInfo', xxxx.as_view(), name='AccountsInfo')
]
urlpatterns += router.urls

需要注意的是 router.register('HomeMenu', ...) 直接固化了主页菜单相关请求的路由前缀。

定位对象数据模型;目的以公司维度存储主页配置数据,配置主体落在 JSON 字段中。

python 复制代码
from django.db import models
from dvadmin.system.models import CoreModel
from dvadmin.utils.models import SoftDeleteModel
from plugins.dv3admin_flow.base_model import FlowBaseModel


# 主页菜单
class HomeMenu(CoreModel, SoftDeleteModel):
    key = models.CharField(max_length=255, null=True, blank=True, verbose_name="键值")
    company = models.CharField(max_length=255, null=True, blank=True, verbose_name='公司名称')
    setting_data = models.JSONField(null=True, blank=True, verbose_name='配置数据')

    class Meta:
        db_table = 'HengShenGroup_Home_HomeMenu'
        verbose_name = '各模块主页菜单'
        verbose_name_plural = verbose_name

需要注意的是 companykey 均允许为空,过滤条件缺失时可能导致"空公司配置"被命中。

字段 类型 可空 用途
key CharField 配置分类键值
company CharField 公司范围标识
setting_data JSONField 主页配置数据载体

定位对象迁移演进;目的展示主页配置字段调整轨迹,最终收敛到 JSON 配置与键值字段。

python 复制代码
# Generated by Django 4.2.14 on 2025-09-30 08:43

from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ("Home", "0003_initial"),
    ]

    operations = [
        migrations.AddField(
            model_name="homemenu",
            name="enable",
            field=models.BooleanField(
                default=True, help_text="是否主页显示", verbose_name="是否启用"
            ),
        ),
    ]

这一步不能省略的校验点在于字段频繁变更时,线上数据与接口字段读取需要同步对齐。

python 复制代码
# Generated by Django 4.2.14 on 2025-09-30 08:47

from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ("Home", "0004_homemenu_enable"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="homemenu",
            name="enable",
        ),
        migrations.RemoveField(
            model_name="homemenu",
            name="name_part",
        ),
        migrations.AddField(
            model_name="homemenu",
            name="setting_data",
            field=models.JSONField(blank=True, null=True, verbose_name="配置数据"),
        ),
    ]

需要注意的是 setting_data 被引入后,主页结构能力从"开关字段"转向"配置数据驱动"。

python 复制代码
# Generated by Django 4.2.14 on 2025-11-13 08:13

from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ("Home", "0005_remove_homemenu_enable_remove_homemenu_name_part_and_more"),
    ]

    operations = [
        migrations.AddField(
            model_name="homemenu",
            name="key",
            field=models.CharField(
                blank=True, max_length=255, null=True, verbose_name="键值"
            ),
        ),
        migrations.AlterField(
            model_name="homemenu",
            name="company",
            field=models.CharField(
                blank=True, max_length=255, null=True, verbose_name="公司名称"
            ),
        ),
    ]

需要注意的是 key 字段加入后,主页配置可以通过键值进行进一步分组与复用。

定位对象查询过滤;目的根据登录态与 company 参数限定可见配置范围,并在 list 动作中固定 key='home'

python 复制代码
# coding:utf-8
'''
@IDE     :PyCharm 
@Project :ManageBak-NDAY.py 
@File    :HomeMenu.py
@Author  :Mr数据杨
@Date    :2025/2/26
@Desc    : 
'''

from dvadmin.utils.viewset import CustomModelViewSet
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.json_response import SuccessResponse, ErrorResponse
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from dvadmin.system.models import DataVisualizationComponent
...
        user = self.request.user
        if not user or user.is_anonymous:
            return qs.none()

        company = self.request.query_params.get("company")
        use_company = user.company  # 登录后 user.company 才是安全的

        if company is not None and company not in use_company:
            return qs.none()

        if self.action == "list":
            qs = qs.filter(company=company, key='home')

        return qs

需要注意的是 company not in use_company 属于包含判断,user.company 数据类型会直接影响判断语义与越权拦截效果。

过滤点 触发条件 结果
登录态校验 user 为空或匿名 返回空数据集
公司范围校验 company 存在且不在 user.company 范围 返回空数据集
列表动作过滤 action 为 list 追加 company=companykey='home'

列表动作筛选
公司范围
鉴权入口
接入请求上下文
读取登录用户
匿名用户拦截
读取公司参数
读取用户公司范围
公司范围不匹配拦截
识别列表动作
限定主页配置范围
输出数据集

总结

主页动态配置的核心落点是 HomeMenu 表的 JSON 配置承载,以及 list 动作中对 key='home' 的固定过滤,路由入口通过 DefaultRouter 统一对外暴露。可优化空间集中在 company 参数为空时的过滤语义与空公司数据命中风险,以及 company not in use_company 的包含判断语义稳定性。

结构收敛到键值分组与 JSON 配置后,主页展示能够通过数据驱动稳定迭代,同时强化公司范围控制可提升维护性与权限边界稳定性。

相关推荐
ding_zhikai2 小时前
【Web应用开发笔记】Django笔记8:用户账户相关功能
笔记·后端·python·django
cnnews2 小时前
在AWS Lambda上部署 tokenizers
python·云计算·numpy·aws·lambda·onnxruntime·tokenizers
清水白石0082 小时前
Python 虚拟环境完全指南:venv、virtualenv、conda、pipenv 深度对比与实战选择
python·conda·virtualenv
EnglishJun2 小时前
Linux系统编程(十)--- 数据库Sqlite3
数据库·sqlite
明月(Alioo)2 小时前
手撕 Agent 教程 - 打造一个轻量级个人智能助手
python·ai
阿部多瑞 ABU2 小时前
Python爬虫实战:话本小说网通用爬虫开发指南
开发语言·爬虫·python
杜子不疼.2 小时前
Python+AI 实战:搭建属于你的智能问答机器人
人工智能·python·机器人
wangjing_05222 小时前
使用python编程贪吃蛇单机小游戏(超详细讲解)
python·pygame
会员源码网8 小时前
Python中生成器函数与普通函数的区别
python