Django-Vue-Admin实战:从零构建一个带数据权限和导入导出的‘项目管理系统’
Django-Vue-Admin实战从零构建带数据权限的项目管理系统初创团队在快速迭代过程中项目管理工具往往成为效率提升的关键瓶颈。传统方案要么功能过剩导致学习成本高要么过于简陋无法满足基本的数据隔离需求。本文将基于Django-Vue-Admin脚手架演示如何快速构建具备行级数据权限和Excel导入导出功能的轻量级项目管理系统。1. 环境准备与项目初始化在开始前确保已安装Python 3.8和Node.js 14环境。推荐使用虚拟环境隔离依赖# 创建并激活Python虚拟环境 python -m venv venv source venv/bin/activate # Linux/Mac venv\Scripts\activate # Windows # 安装脚手架 pip install django-vue-admin-cli dva-cli init project_manager初始化后的项目结构包含三个核心目录dvadmin-backendDjango后端服务dvadmin-uiVue前端工程scripts部署脚本提示Windows用户若遇到路径问题建议在PowerShell中执行命令。初始化过程会自动安装MySQL驱动如需改用PostgreSQL需额外安装psycopg2包。2. 数据模型设计与权限控制在dvadmin-backend/apps/project/models目录下创建project.py文件定义核心数据模型from django.db import models from vadmin.op_drf.models import CoreModel class Project(CoreModel): PROJECT_STATUS ( (0, 规划中), (1, 进行中), (2, 已延期), (3, 已完成) ) name models.CharField(max_length64, verbose_name项目名称) code models.CharField(max_length32, uniqueTrue, verbose_name项目编码) owner models.ForeignKey( topermission.users, on_deletemodels.SET_NULL, nullTrue, verbose_name项目负责人 ) department models.ForeignKey( topermission.dept, on_deletemodels.CASCADE, verbose_name所属部门 ) status models.SmallIntegerField( choicesPROJECT_STATUS, default0, verbose_name项目状态 ) deadline models.DateField(verbose_name截止日期) class Meta: verbose_name 项目信息 verbose_name_plural verbose_name # 按部门自动过滤数据 data_level_permission True def __str__(self): return f{self.code}-{self.name}关键设计要点继承CoreModel获得软删除、审计字段等基础功能通过data_level_permission开启自动数据权限过滤外键关联使用框架预置的用户和部门模型3. 实现行级数据权限控制Django-Vue-Admin通过DataLevelPermissionsFilter实现行级数据过滤。在视图层配置如下from apps.vadmin.op_drf.filters import DataLevelPermissionsFilter from rest_framework import viewsets class ProjectViewSet(viewsets.ModelViewSet): queryset Project.objects.all() serializer_class ProjectSerializer filter_backends [DataLevelPermissionsFilter] # 启用数据权限过滤 def get_queryset(self): # 基础查询集处理 queryset super().get_queryset() # 添加自定义过滤逻辑 return queryset.filter( department__inself.request.user.departments.all() )权限控制效果对比用户角色可见数据范围操作权限超级管理员全部项目全部CRUD部门主管本部门项目增删改本部门项目普通成员参与的项目仅查看注意数据权限配置需配合前端菜单权限使用。建议在permission应用中进行角色-菜单-权限的完整配置。4. 复杂数据导出实现系统内置的导出功能支持自定义字段处理。创建export_serializers.pyclass ProjectExportSerializer(CustomModelSerializer): owner_name serializers.CharField(sourceowner.name, read_onlyTrue) department_name serializers.CharField(sourcedepartment.name) status_display serializers.SerializerMethodField() def get_status_display(self, obj): return dict(Project.PROJECT_STATUS).get(obj.status) class Meta: model Project fields [ code, name, owner_name, department_name, status_display, deadline, description ] export_fields [ (项目编码, code), (项目名称, name), (负责人, owner_name), (所属部门, department_name), (项目状态, status_display), (截止日期, deadline), (项目描述, description) ]视图层配置导出参数class ProjectViewSet(viewsets.ModelViewSet): export_serializer_class ProjectExportSerializer export_file_name 项目列表_导出_{date} export_exclude_fields [id, creator, modifier]导出功能支持的特性自动处理关联字段显示支持Excel/CSV/PDF格式自定义导出列名映射自动文件命名模板5. 前端界面配置实战在dvadmin-ui/src/views/project目录下创建界面组件// index.vue template model-display :listApilistApi :fieldsfields :funcsfuncs :exportConfigexportConfig / /template script export default { data() { return { fields: [ { prop: code, label: 项目编码, search: true, required: true }, { prop: name, label: 项目名称, search: { type: input } }, { prop: owner, label: 负责人, type: user-select, form: { required: true } }, { prop: status, label: 状态, type: select, options: [ { label: 规划中, value: 0 }, { label: 进行中, value: 1 }, { label: 已延期, value: 2 }, { label: 已完成, value: 3 } ] } ], funcs: [ { type: add, label: 新建项目, api: addProject }, { type: import, label: 批量导入, api: importProject }, { type: export, label: 导出Excel, api: exportProject } ], exportConfig: { filename: 项目列表, columns: [ { label: 项目编码, prop: code }, { label: 项目名称, prop: name }, { label: 负责人, prop: owner_name }, { label: 当前状态, prop: status_display } ] } } } } /script前端配置关键点fields定义表格列和表单字段funcs配置操作按钮和对应API支持动态权限控制通过permis属性导出配置与后端序列化器对应6. 高级功能扩展6.1 自定义数据导入在serializers.py中添加导入校验逻辑class ProjectImportSerializer(serializers.ModelSerializer): department serializers.PrimaryKeyRelatedField( querysetDepartment.objects.all(), requiredTrue, error_messages{does_not_exist: 指定部门不存在} ) def validate_code(self, value): if Project.objects.filter(codevalue).exists(): raise serializers.ValidationError(项目编码已存在) return value class Meta: model Project fields __all__6.2 定时任务集成利用框架的celery扩展实现自动状态更新# tasks.py app.task def auto_update_project_status(): overdue Project.objects.filter( deadline__lttimezone.now(), status__lt2 ).update(status2) return f更新{overdue}个过期项目6.3 消息通知配置在模型保存时触发通知# signals.py receiver(post_save, senderProject) def project_update_notice(sender, instance, created, **kwargs): if created: notify.send( instance.creator, recipientinstance.owner, verbf您被指派为项目[{instance.name}]的负责人 )7. 性能优化实践针对大数据量场景的优化方案数据库优化queryset Project.objects.select_related( owner, department ).only( code, name, status, owner__name, department__name )前端分页配置// 在vue组件中 pagination: { pageSize: 20, pageSizes: [10, 20, 50, 100], layout: total, sizes, prev, pager, next, jumper }缓存策略class ProjectViewSet(viewsets.ModelViewSet): method_decorator(cache_page(60*5)) def list(self, request): return super().list(request)实际部署时建议使用Nginx进行静态资源缓存并通过Django的DEBUG_TOOLBAR监控查询性能。