【Django + Pure Admin】基于Django+Vue3的前后端分离管理系统框架设计
Django Pure Admin 完整技术文档 - 基于Django+Vue3的前后端分离管理系统
本文详细介绍了一个基于Django+Vue3的前后端分离管理系统的完整开发过程,包含技术架构、核心功能、代码实现和部署方案。
📋 目录
- 🎯 项目概述
- 🏗️ 技术架构
- 🛠️ 开发环境
- 💾 数据库设计
- 🔧 后端实现
- 🎨 前端实现
- 📱 系统功能展示
- 🚀 部署指南
- 📚 开发指南
- ❓ 常见问题
🎯 项目概述
项目简介
Django Pure Admin 是一个基于 Django + Vue3 的前后端分离管理系统,采用现代化的技术栈和架构设计,提供完整的用户管理、权限控制、菜单管理等功能。
核心特性
- ✅ 前后端分离架构:后端提供RESTful API,前端独立开发和部署
- ✅ 精细化权限控制:基于RBAC模型,支持菜单级和按钮级权限
- ✅ 动态菜单管理:支持前端控制和后端控制两种菜单管理模式
- ✅ 现代化UI设计:基于Element Plus,响应式布局,支持多主题切换
- ✅ 完整的用户体系:用户管理、角色管理、权限管理、部门管理
- ✅ 系统监控功能:操作日志、登录日志、系统通知
- ✅ 开发友好:TypeScript支持、完整的开发文档、代码规范
技术栈
层级 | 技术栈 | 版本 | 说明 |
---|---|---|---|
前端 | Vue3 + TypeScript + Vite | 3.4.0+ | 现代化前端框架 |
UI组件 | Element Plus | 2.4.0+ | 企业级UI组件库 |
状态管理 | Pinia | 2.1.0+ | Vue3状态管理 |
路由 | Vue Router 4 | 4.2.0+ | 前端路由管理 |
HTTP客户端 | Axios | 1.6.0+ | HTTP请求库 |
后端 | Django + DRF | 5.2.5+ | Python Web框架 |
数据库 | MySQL | 5.7+ | 关系型数据库 |
认证 | JWT | 5.3.0+ | 无状态认证 |
文档 | Swagger | 1.21.7+ | API文档生成 |
🏗️ 技术架构
整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ 前端层 (Frontend) │
├─────────────────────────────────────────────────────────────────┤
│ Vue3 + TypeScript + Vite + Element Plus + Pinia + Vue Router │
│ ├─ 用户界面 (UI Components) │
│ ├─ 状态管理 (Pinia Store) │
│ ├─ 路由管理 (Vue Router) │
│ ├─ HTTP客户端 (Axios) │
│ └─ 构建工具 (Vite) │
└─────────────────────────────────────────────────────────────────┘│▼
┌─────────────────────────────────────────────────────────────────┐
│ API网关层 (API Gateway) │
├─────────────────────────────────────────────────────────────────┤
│ Django REST Framework + JWT Authentication + CORS │
│ ├─ 认证授权 (Authentication & Authorization) │
│ ├─ 请求处理 (Request Processing) │
│ ├─ 响应格式化 (Response Formatting) │
│ └─ 跨域处理 (CORS Handling) │
└─────────────────────────────────────────────────────────────────┘│▼
┌─────────────────────────────────────────────────────────────────┐
│ 业务逻辑层 (Business Logic) │
├─────────────────────────────────────────────────────────────────┤
│ Django Views + Serializers + Filters + Pagination │
│ ├─ 视图控制器 (View Controllers) │
│ ├─ 数据序列化 (Data Serialization) │
│ ├─ 数据过滤 (Data Filtering) │
│ ├─ 分页处理 (Pagination) │
│ └─ 业务逻辑 (Business Logic) │
└─────────────────────────────────────────────────────────────────┘│▼
┌─────────────────────────────────────────────────────────────────┐
│ 数据访问层 (Data Access) │
├─────────────────────────────────────────────────────────────────┤
│ Django ORM + Models + Migrations │
│ ├─ 数据模型 (Data Models) │
│ ├─ 对象关系映射 (ORM) │
│ ├─ 数据库迁移 (Migrations) │
│ └─ 查询优化 (Query Optimization) │
└─────────────────────────────────────────────────────────────────┘│▼
┌─────────────────────────────────────────────────────────────────┐
│ 数据存储层 (Data Storage) │
├─────────────────────────────────────────────────────────────────┤
│ MySQL 5.7+ + Redis (可选) │
│ ├─ 关系型数据库 (MySQL) │
│ ├─ 缓存数据库 (Redis) │
│ └─ 文件存储 (File Storage) │
└─────────────────────────────────────────────────────────────────┘
项目结构
Django_Pure/
├── Backend/ # Django后端
│ ├── application/ # Django项目配置
│ │ ├── settings.py # 项目设置
│ │ ├── urls.py # 主路由配置
│ │ └── wsgi.py # WSGI配置
│ ├── App/ # 主应用
│ │ ├── models.py # 数据模型
│ │ ├── serializers.py # 序列化器
│ │ ├── views.py # 视图
│ │ ├── urls.py # 路由
│ │ └── admin.py # 管理员配置
│ ├── manage.py # Django管理脚本
│ └── requirements.txt # Python依赖
├── Frontend/ # Vue3前端
│ ├── src/
│ │ ├── api/ # API接口
│ │ ├── components/ # 公共组件
│ │ ├── layout/ # 布局组件
│ │ ├── router/ # 路由配置
│ │ ├── store/ # 状态管理
│ │ ├── views/ # 页面组件
│ │ └── utils/ # 工具函数
│ ├── package.json # 前端依赖
│ └── vite.config.ts # Vite配置
└── images/ # 项目截图├── 登录.png├── 首页.png├── 用户管理.png└── ...
🛠️ 开发环境
环境要求
- 操作系统: Windows 10+, macOS 10.15+, Ubuntu 18.04+
- Python: 3.8+ (推荐3.11)
- Node.js: 16+ (推荐18+)
- MySQL: 5.7+ (推荐8.0+)
- 内存: 8GB+ (推荐16GB)
- 存储: 10GB+ 可用空间
环境配置
1. Python环境配置
# 创建虚拟环境
python -m venv django_pure_env# 激活虚拟环境
# Windows
django_pure_env\Scripts\activate
# Linux/Mac
source django_pure_env/bin/activate# 升级pip
pip install --upgrade pip# 安装后端依赖
cd Backend
pip install -r requirements.txt
2. Node.js环境配置
# 检查Node.js版本
node --version
npm --version# 安装pnpm (推荐)
npm install -g pnpm# 安装前端依赖
cd Frontend
pnpm install
3. 数据库环境配置
-- 创建数据库
CREATE DATABASE django_pure CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;-- 创建用户
CREATE USER 'django_pure'@'localhost' IDENTIFIED BY 'your_password';-- 授权
GRANT ALL PRIVILEGES ON django_pure.* TO 'django_pure'@'localhost';
FLUSH PRIVILEGES;
💾 数据库设计
数据库架构图
┌─────────────────────────────────────────────────────────────────┐
│ Django Pure Admin │
│ 数据库设计 │
└─────────────────────────────────────────────────────────────────┘┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 用户认证模块 │ │ 权限管理模块 │ │ 菜单管理模块 │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ auth_user │ │ auth_group │ │ system_menu │
│ auth_user_groups│ │ auth_permission │ │ system_role │
│ auth_group_perms│ │ user_permissions│ │ role_menus │
└─────────────────┘ └─────────────────┘ └─────────────────┘│ │ │└───────────────────────┼───────────────────────┘│┌─────────────────┐│ 系统管理模块 │├─────────────────┤│ system_user ││ system_dept ││ system_log ││ system_notify │└─────────────────┘
核心数据表
1. 用户表 (auth_user)
CREATE TABLE `auth_user` (`id` int(11) NOT NULL AUTO_INCREMENT,`password` varchar(128) NOT NULL,`last_login` datetime(6) DEFAULT NULL,`is_superuser` tinyint(1) NOT NULL,`username` varchar(150) NOT NULL,`first_name` varchar(150) NOT NULL,`last_name` varchar(150) NOT NULL,`email` varchar(254) NOT NULL,`is_staff` tinyint(1) NOT NULL,`is_active` tinyint(1) NOT NULL,`date_joined` datetime(6) NOT NULL,`realName` varchar(150) DEFAULT NULL,`phone` varchar(150) DEFAULT NULL,`avatar` varchar(100) DEFAULT NULL,`gender` varchar(1) DEFAULT NULL,`desc` longtext DEFAULT NULL,`homePath` varchar(255) DEFAULT '/profile/info',PRIMARY KEY (`id`),UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 菜单表 (system_menu)
CREATE TABLE `system_menu` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(100) NOT NULL,`path` varchar(255) NOT NULL,`component` varchar(255) DEFAULT NULL,`redirect` varchar(255) DEFAULT NULL,`meta` json DEFAULT NULL,`parent_id` int(11) DEFAULT NULL,`order` int(11) DEFAULT 0,PRIMARY KEY (`id`),KEY `parent_id` (`parent_id`),CONSTRAINT `system_menu_parent_id_fkey` FOREIGN KEY (`parent_id`) REFERENCES `system_menu` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 通知表 (system_notification)
CREATE TABLE `system_notification` (`id` int(11) NOT NULL AUTO_INCREMENT,`sender_id` int(11) NOT NULL,`notification_type` varchar(20) NOT NULL DEFAULT 'system',`title` varchar(200) NOT NULL,`message` longtext NOT NULL,`link` varchar(500) DEFAULT NULL,`created_at` datetime(6) NOT NULL,`updated_at` datetime(6) NOT NULL,PRIMARY KEY (`id`),KEY `sender_id` (`sender_id`),CONSTRAINT `system_notification_sender_id_fkey` FOREIGN KEY (`sender_id`) REFERENCES `auth_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
🔧 后端实现
1. 数据模型设计
用户模型扩展
# Backend/App/models.pyfrom django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _class User(AbstractUser):"""扩展的用户模型"""GENDER_CHOICES = [('M', '男'),('F', '女'),('O', '其他'),]realName = models.CharField(_("Real name"), max_length=150, blank=True)phone = models.CharField(_("Phone"), max_length=150, blank=True)avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)gender = models.CharField(_("Gender"), max_length=1, choices=GENDER_CHOICES, blank=True, null=True)desc = models.TextField(_("Description"), blank=True)homePath = models.CharField(_("Home path"), max_length=255, default="/profile/info")class Meta:verbose_name = _("user")verbose_name_plural = _("users")class Menu(models.Model):"""菜单模型"""name = models.CharField(max_length=100)path = models.CharField(max_length=255)component = models.CharField(max_length=255, blank=True, null=True)redirect = models.CharField(max_length=255, blank=True)meta = models.JSONField(default=dict)parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')order = models.IntegerField(default=0)groups = models.ManyToManyField('auth.Group', related_name='menus')class Meta:verbose_name = '菜单'verbose_name_plural = '菜单'def __str__(self):return self.nameclass Notification(models.Model):"""通知模型"""NOTIFICATION_TYPES = [('system', '系统通知'),('user', '用户通知'),('task', '任务通知'),('message', '消息通知'),]sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_notifications', verbose_name='发起人')recipients = models.ManyToManyField(User, related_name='received_notifications', verbose_name='接收人')notification_type = models.CharField(max_length=20, choices=NOTIFICATION_TYPES, default='system', verbose_name='通知类型')title = models.CharField(max_length=200, verbose_name='标题')message = models.TextField(verbose_name='描述')link = models.CharField(max_length=500, blank=True, null=True, verbose_name='跳转链接')created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')class Meta:verbose_name = '通知'verbose_name_plural = '通知'ordering = ['-created_at']def __str__(self):return f"{self.title}"
2. 序列化器实现
# Backend/App/serializers.pyfrom rest_framework import serializers
from django.contrib.auth import authenticate
from .models import User, Menu, Notificationclass LoginSerializer(serializers.Serializer):"""用户登录序列化器"""username = serializers.CharField()password = serializers.CharField(write_only=True)device_info = serializers.DictField(required=False)def validate(self, attrs):username = attrs.get('username')password = attrs.get('password')if username and password:user = authenticate(username=username, password=password)if user:if not user.is_active:raise serializers.ValidationError("User account is disabled.")attrs['user'] = userreturn attrselse:raise serializers.ValidationError("Invalid username or password.")else:raise serializers.ValidationError("Must include 'username' and 'password'.")class UserInfoSerializer(serializers.ModelSerializer):"""用户信息序列化器"""roles = serializers.SerializerMethodField()class Meta:model = Userfields = ('id', 'username', 'avatar', 'realName', 'phone', 'email', 'desc', 'homePath', 'roles')def get_roles(self, obj):return list(obj.groups.values_list('name', flat=True))class MenuSerializer(serializers.ModelSerializer):"""菜单序列化器"""children = serializers.SerializerMethodField()class Meta:model = Menufields = ('id', 'name', 'path', 'component', 'redirect', 'meta', 'children')def get_children(self, obj):children = obj.children.all().order_by('order')return MenuSerializer(children, many=True).data
3. 视图实现
# Backend/App/views.pyfrom rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from django.utils import timezone
from .serializers import *
from .models import *class AuthViewSet(viewsets.ViewSet):"""认证视图集"""@action(detail=False, methods=['post'], permission_classes=[permissions.AllowAny], url_path='login')def login(self, request):"""用户登录"""serializer = LoginSerializer(data=request.data)serializer.is_valid(raise_exception=True)user = serializer.validated_data['user']refresh = RefreshToken.for_user(user)# 记录登录设备信息try:device_data = request.data.get('device_info', {})if device_data:from .models import LoginDeviceexisting_device = LoginDevice.objects.filter(user=user,device_id=device_data.get('device_id')).first()if existing_device:existing_device.last_login = timezone.now()existing_device.ip_address = device_data.get('ip_address', request.META.get('REMOTE_ADDR', '127.0.0.1'))existing_device.save()else:LoginDevice.objects.create(user=user,device_id=device_data.get('device_id'),device_name=device_data.get('device_name'),browser=device_data.get('browser'),os=device_data.get('os'),ip_address=device_data.get('ip_address', request.META.get('REMOTE_ADDR', '127.0.0.1')),location=device_data.get('location'),user_agent=device_data.get('user_agent', request.META.get('HTTP_USER_AGENT', '')),is_current=False)except Exception as e:print(f"Failed to record device info: {e}")return Response({'code': 0,'message': '登录成功','data': {'access_token': str(refresh.access_token),'refresh_token': str(refresh),'user_info': UserInfoSerializer(user).data}})@action(detail=False, methods=['get'], permission_classes=[permissions.IsAuthenticated], url_path='user-info')def user_info(self, request):"""获取用户信息"""user = request.userreturn Response({'code': 0,'message': 'success','data': UserInfoSerializer(user).data})class MenuViewSet(viewsets.ModelViewSet):"""菜单管理视图集"""queryset = Menu.objects.all()serializer_class = MenuSerializerpermission_classes = [permissions.IsAuthenticated]@action(detail=False, methods=['get'], url_path='user-menus')def user_menus(self, request):"""获取当前用户的菜单"""user = request.useruser_groups = user.groups.all()# 获取用户有权限的菜单menus = Menu.objects.filter(groups__in=user_groups).distinct()# 构建菜单树menu_tree = []menu_dict = {}for menu in menus:menu_dict[menu.id] = {'id': menu.id,'name': menu.name,'path': menu.path,'component': menu.component,'redirect': menu.redirect,'meta': menu.meta,'children': []}for menu in menus:if menu.parent is None:menu_tree.append(menu_dict[menu.id])else:if menu.parent.id in menu_dict:menu_dict[menu.parent.id]['children'].append(menu_dict[menu.id])return Response({'code': 0,'message': 'success','data': menu_tree})
🎨 前端实现
1. 项目结构
Frontend/
├── src/
│ ├── api/ # API接口
│ │ ├── auth.ts # 认证相关API
│ │ ├── user.ts # 用户管理API
│ │ └── menu.ts # 菜单管理API
│ ├── components/ # 公共组件
│ │ ├── ReIcon/ # 图标组件
│ │ ├── ReDialog/ # 对话框组件
│ │ └── ReDrawer/ # 抽屉组件
│ ├── layout/ # 布局组件
│ │ ├── components/ # 布局子组件
│ │ └── index.vue # 主布局
│ ├── router/ # 路由配置
│ │ ├── index.ts # 路由主文件
│ │ └── utils.ts # 路由工具
│ ├── store/ # 状态管理
│ │ ├── modules/ # Store模块
│ │ └── index.ts # Store主文件
│ ├── views/ # 页面组件
│ │ ├── login/ # 登录页
│ │ ├── system/ # 系统管理
│ │ └── welcome/ # 欢迎页
│ └── utils/ # 工具函数
│ ├── auth.ts # 认证工具
│ └── http/ # HTTP工具
├── package.json # 依赖配置
└── vite.config.ts # Vite配置
2. API接口层
// Frontend/src/api/auth.tsimport request from '@/utils/http'export interface LoginParams {username: stringpassword: stringdevice_info?: any
}export interface UserInfo {id: numberusername: stringavatar?: stringrealName?: stringphone?: stringemail?: stringdesc?: stringhomePath?: stringroles?: string[]
}export interface LoginResponse {access_token: stringrefresh_token: stringuser_info: UserInfo
}// 认证相关API
export const authApi = {// 用户登录login: (data: LoginParams) => {return request.post<LoginResponse>('/auth/login', data)},// 获取用户信息getUserInfo: () => {return request.get<UserInfo>('/auth/user-info')},// 用户登出logout: (data: { refresh_token: string }) => {return request.post('/auth/logout', data)}
}
3. 状态管理
// Frontend/src/store/modules/user.tsimport { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { authApi } from '@/api'
import type { UserInfo, LoginParams } from '@/api/auth'export const useUserStore = defineStore('user', () => {// 状态const token = ref<string>('')const userInfo = ref<UserInfo | null>(null)const roles = ref<string[]>([])// 计算属性const isLoggedIn = computed(() => !!token.value)const hasRole = computed(() => (role: string) => roles.value.includes(role))// 获取Tokenconst getToken = () => {return localStorage.getItem('token') || ''}// 设置Tokenconst setToken = (newToken: string) => {token.value = newTokenlocalStorage.setItem('token', newToken)}// 获取用户信息const getUserInfo = async () => {try {const data = await authApi.getUserInfo()userInfo.value = dataroles.value = data.roles || []return data} catch (error) {console.error('Get user info error:', error)throw error}}// 用户登录const login = async (loginParams: LoginParams) => {try {const data = await authApi.login(loginParams)setToken(data.access_token)userInfo.value = data.user_inforoles.value = data.user_info.roles || []return data} catch (error) {console.error('Login error:', error)throw error}}// 用户登出const logout = async () => {try {if (token.value) {const refreshToken = localStorage.getItem('refresh_token')if (refreshToken) {await authApi.logout({ refresh_token: refreshToken })}}} catch (error) {console.error('Logout error:', error)} finally {resetUserInfo()}}// 重置用户信息const resetUserInfo = () => {token.value = ''userInfo.value = nullroles.value = []localStorage.removeItem('token')localStorage.removeItem('refresh_token')}return {// 状态token,userInfo,roles,// 计算属性isLoggedIn,hasRole,// 方法getToken,setToken,getUserInfo,login,logout,resetUserInfo}
})
4. 路由配置
// Frontend/src/router/index.tsimport { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { useUserStore } from '@/store/modules/user'
import { usePermissionStore } from '@/store/modules/permission'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'// 静态路由
export const constantRoutes: RouteRecordRaw[] = [{path: '/login',name: 'Login',component: () => import('@/views/login/index.vue'),meta: {title: '登录',hidden: true}},{path: '/',name: 'Layout',component: () => import('@/layout/index.vue'),redirect: '/welcome',meta: {title: '首页',hidden: false},children: [{path: '/welcome',name: 'Welcome',component: () => import('@/views/welcome/index.vue'),meta: {title: '欢迎页',icon: 'ep:house',affix: true}}]}
]// 动态路由
export const asyncRoutes: RouteRecordRaw[] = [{path: '/system',name: 'System',component: () => import('@/layout/index.vue'),redirect: '/system/user',meta: {title: '系统管理',icon: 'ep:setting',roles: ['admin']},children: [{path: '/system/user',name: 'SystemUser',component: () => import('@/views/system/user/index.vue'),meta: {title: '用户管理',icon: 'ep:user',roles: ['admin']}},{path: '/system/menu',name: 'SystemMenu',component: () => import('@/views/system/menu/index.vue'),meta: {title: '菜单管理',icon: 'ep:menu',roles: ['admin']}}]}
]const router = createRouter({history: createWebHistory(),routes: constantRoutes,scrollBehavior: () => ({ left: 0, top: 0 })
})// 路由守卫
router.beforeEach(async (to, from, next) => {NProgress.start()const userStore = useUserStore()const permissionStore = usePermissionStore()// 设置页面标题document.title = to.meta.title ? `${to.meta.title} - Django Pure Admin` : 'Django Pure Admin'// 检查是否需要登录if (to.path === '/login') {if (userStore.token) {next({ path: '/' })} else {next()}return}// 检查是否已登录if (!userStore.token) {next({ path: '/login', query: { redirect: to.fullPath } })return}// 检查是否已获取用户信息if (!userStore.userInfo) {try {await userStore.getUserInfo()} catch (error) {userStore.logout()next({ path: '/login', query: { redirect: to.fullPath } })return}}// 检查是否已生成路由if (!permissionStore.isRoutesGenerated) {try {await permissionStore.generateRoutes()permissionStore.routes.forEach(route => {router.addRoute(route)})next({ ...to, replace: true })return} catch (error) {console.error('Generate routes error:', error)next({ path: '/login' })return}}next()
})router.afterEach(() => {NProgress.done()
})export default router
📱 系统功能展示
1. 登录页面
功能特点:
- 现代化的登录界面设计
- 支持用户名/密码登录
- 设备信息记录
- 响应式布局适配
技术实现:
- 基于Element Plus组件库
- JWT Token认证
- 设备指纹识别
- 表单验证
2. 系统首页
功能特点:
- 数据统计展示
- 快捷操作入口
- 系统状态监控
- 个性化欢迎信息
技术实现:
- ECharts图表展示
- 实时数据更新
- 响应式布局
- 主题切换
3. 用户管理
功能特点:
- 用户列表展示
- 搜索和筛选
- 新增/编辑/删除用户
- 角色分配
- 状态管理
技术实现:
- 表格组件
- 分页功能
- 表单验证
- 权限控制
4. 菜单管理
功能特点:
- 树形菜单展示
- 菜单层级管理
- 权限配置
- 图标选择
- 排序功能
技术实现:
- 树形组件
- 拖拽排序
- 图标选择器
- 权限验证
5. 角色管理
功能特点:
- 角色列表管理
- 权限分配
- 用户关联
- 角色继承
技术实现:
- 权限树组件
- 多选功能
- 数据关联
- 批量操作
6. 系统设置
功能特点:
- 系统参数配置
- 主题设置
- 语言切换
- 个人偏好
技术实现:
- 配置管理
- 主题系统
- 国际化
- 本地存储
7. 个人信息
功能特点:
- 个人信息展示
- 头像上传
- 密码修改
- 偏好设置
技术实现:
- 文件上传
- 表单验证
- 实时预览
- 数据同步
8. 账户管理
功能特点:
- 账户信息管理
- 安全设置
- 登录设备管理
- 操作日志
技术实现:
- 设备管理
- 安全验证
- 日志记录
- 数据导出
🚀 部署指南
1. 开发环境启动
后端启动
# 进入后端目录
cd Backend# 激活虚拟环境
# Windows
venv\Scripts\activate
# Linux/Mac
source venv/bin/activate# 安装依赖
pip install -r requirements.txt# 配置数据库
# 修改 .env 文件中的数据库配置# 执行数据库迁移
python manage.py makemigrations
python manage.py migrate# 创建超级用户
python manage.py createsuperuser# 启动开发服务器
python manage.py runserver
前端启动
# 进入前端目录
cd Frontend# 安装依赖
pnpm install# 配置环境变量
# 修改 .env 文件中的API地址# 启动开发服务器
pnpm dev
2. 生产环境部署
Docker部署方案
后端Dockerfile
# Backend/Dockerfile
FROM python:3.11-slimWORKDIR /app# 安装系统依赖
RUN apt-get update && apt-get install -y \gcc \default-libmysqlclient-dev \&& rm -rf /var/lib/apt/lists/*# 复制依赖文件
COPY requirements.txt .
RUN pip install -r requirements.txt# 复制项目文件
COPY . .# 创建静态文件目录
RUN mkdir -p /app/staticfiles /app/media# 暴露端口
EXPOSE 8000# 启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "application.wsgi:application"]
前端Dockerfile
# Frontend/Dockerfile
FROM node:18-alpine as buildWORKDIR /app# 复制依赖文件
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install# 复制源代码
COPY . .# 构建项目
RUN pnpm build# 生产环境
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.confEXPOSE 80CMD ["nginx", "-g", "daemon off;"]
Docker Compose配置
# docker-compose.yml
version: '3.8'services:# MySQL数据库db:image: mysql:8.0container_name: django_pure_dbenvironment:MYSQL_ROOT_PASSWORD: your_root_passwordMYSQL_DATABASE: django_pureMYSQL_USER: django_pureMYSQL_PASSWORD: your_passwordvolumes:- mysql_data:/var/lib/mysql- ./Backend/django_pure.sql:/docker-entrypoint-initdb.d/init.sqlports:- "3306:3306"networks:- django_pure_network# Redis缓存redis:image: redis:7-alpinecontainer_name: django_pure_redisports:- "6379:6379"networks:- django_pure_network# Django后端backend:build: ./Backendcontainer_name: django_pure_backendenvironment:- DEBUG=False- DB_HOST=db- DB_NAME=django_pure- DB_USER=django_pure- DB_PASSWORD=your_password- REDIS_HOST=redis- REDIS_PORT=6379volumes:- ./Backend/media:/app/media- ./Backend/staticfiles:/app/staticfilesdepends_on:- db- redisports:- "8000:8000"networks:- django_pure_network# Vue前端frontend:build: ./Frontendcontainer_name: django_pure_frontendports:- "80:80"depends_on:- backendnetworks:- django_pure_networkvolumes:mysql_data:networks:django_pure_network:driver: bridge
Nginx配置
# Frontend/nginx.conf
events {worker_connections 1024;
}http {include /etc/nginx/mime.types;default_type application/octet-stream;# Gzip压缩gzip on;gzip_vary on;gzip_min_length 1024;gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;# 上游服务器upstream backend {server backend:8000;}server {listen 80;server_name localhost;root /usr/share/nginx/html;index index.html;# 前端路由支持location / {try_files $uri $uri/ /index.html;}# API代理location /api/ {proxy_pass http://backend/api/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;# 超时设置proxy_connect_timeout 30s;proxy_send_timeout 30s;proxy_read_timeout 30s;}# 静态资源缓存location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {expires 1y;add_header Cache-Control "public, immutable";add_header Vary Accept-Encoding;}# 安全头add_header X-Frame-Options "SAMEORIGIN" always;add_header X-XSS-Protection "1; mode=block" always;add_header X-Content-Type-Options "nosniff" always;add_header Referrer-Policy "no-referrer-when-downgrade" always;add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;}
}
3. 部署步骤
# 1. 克隆项目
git clone https://github.com/wangxiaozeze/Django_Pure.git
cd Django_Pure# 2. 配置环境变量
cp Backend/.env.example Backend/.env
# 编辑 Backend/.env 文件,配置数据库等信息# 3. 使用Docker Compose启动
docker-compose up -d# 4. 查看服务状态
docker-compose ps# 5. 查看日志
docker-compose logs -f backend
docker-compose logs -f frontend
📚 开发指南
1. 代码规范
Python代码规范
# 遵循PEP 8规范
# 使用Black进行代码格式化
# 使用isort进行导入排序
# 使用flake8进行代码检查# 安装开发工具
pip install black isort flake8# 格式化代码
black Backend/
isort Backend/# 检查代码
flake8 Backend/
TypeScript代码规范
// Frontend/.eslintrc.js
module.exports = {root: true,env: {browser: true,es2021: true,node: true,},extends: ['eslint:recommended','@vue/typescript/recommended','@vue/prettier','@vue/prettier/@typescript-eslint',],parserOptions: {ecmaVersion: 2021,},rules: {'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',},
}
2. Git工作流
# 1. 创建功能分支
git checkout -b feature/user-management# 2. 开发功能
# ... 编写代码 ...# 3. 提交代码
git add .
git commit -m "feat: 添加用户管理功能"# 4. 推送分支
git push origin feature/user-management# 5. 创建Pull Request
# 在GitHub上创建PR,进行代码审查# 6. 合并到主分支
git checkout main
git merge feature/user-management
git push origin main
3. 测试策略
后端测试
# Backend/App/tests.py
from django.test import TestCase
from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase
from rest_framework import statusUser = get_user_model()class UserModelTest(TestCase):def setUp(self):self.user_data = {'username': 'testuser','email': 'test@example.com','password': 'testpass123'}def test_create_user(self):user = User.objects.create_user(**self.user_data)self.assertEqual(user.username, self.user_data['username'])self.assertEqual(user.email, self.user_data['email'])self.assertTrue(user.check_password(self.user_data['password']))class AuthAPITest(APITestCase):def setUp(self):self.user = User.objects.create_user(username='testuser',password='testpass123')def test_login(self):url = '/api/auth/login/'data = {'username': 'testuser','password': 'testpass123'}response = self.client.post(url, data)self.assertEqual(response.status_code, status.HTTP_200_OK)self.assertIn('access_token', response.data['data'])
前端测试
// Frontend/src/views/login/__tests__/Login.test.ts
import { mount } from '@vue/test-utils'
import { describe, it, expect, vi } from 'vitest'
import Login from '../index.vue'describe('Login Component', () => {it('renders login form', () => {const wrapper = mount(Login)expect(wrapper.find('input[name="username"]').exists()).toBe(true)expect(wrapper.find('input[name="password"]').exists()).toBe(true)expect(wrapper.find('button[type="submit"]').exists()).toBe(true)})it('validates form inputs', async () => {const wrapper = mount(Login)const submitButton = wrapper.find('button[type="submit"]')await submitButton.trigger('click')// 检查验证错误expect(wrapper.text()).toContain('请输入用户名')expect(wrapper.text()).toContain('请输入密码')})
})
4. 性能优化
后端优化
# 1. 数据库查询优化
# 使用select_related和prefetch_related
users = User.objects.select_related('profile').prefetch_related('groups').all()# 2. 缓存策略
from django.core.cache import cachedef get_user_info(user_id):cache_key = f'user_info_{user_id}'user_info = cache.get(cache_key)if user_info is None:user_info = User.objects.get(id=user_id)cache.set(cache_key, user_info, timeout=3600)return user_info# 3. 分页优化
from django.core.paginator import Paginatordef get_paginated_users(page=1, page_size=20):users = User.objects.all()paginator = Paginator(users, page_size)return paginator.get_page(page)
前端优化
// 1. 组件懒加载
const UserManagement = () => import('@/views/system/user/index.vue')// 2. 图片懒加载
<img v-lazy="imageUrl" alt="用户头像" />// 3. 虚拟滚动
import { useVirtualList } from '@vueuse/core'const { list, containerProps, wrapperProps } = useVirtualList(userList,{itemHeight: 60,overscan: 10}
)// 4. 防抖搜索
import { debounce } from 'lodash-es'const debouncedSearch = debounce((keyword: string) => {searchUsers(keyword)
}, 300)
5. 安全措施
后端安全
# 1. CORS配置
CORS_ALLOWED_ORIGINS = ["http://localhost:3000","https://yourdomain.com"
]# 2. 密码加密
from django.contrib.auth.hashers import make_password
user.password = make_password(password)# 3. SQL注入防护
# Django ORM自动防护SQL注入# 4. XSS防护
from django.utils.html import escape
content = escape(user_input)# 5. CSRF防护
# Django自动启用CSRF保护
前端安全
// 1. XSS防护
import DOMPurify from 'dompurify'
const sanitizedHtml = DOMPurify.sanitize(userInput)// 2. 输入验证
import { z } from 'zod'const userSchema = z.object({username: z.string().min(3).max(20),email: z.string().email(),password: z.string().min(6)
})// 3. 敏感信息处理
const maskPassword = (password: string) => '*'.repeat(password.length)// 4. 安全存储
const secureStorage = {setItem: (key: string, value: string) => {// 加密存储const encrypted = encrypt(value)localStorage.setItem(key, encrypted)},getItem: (key: string) => {const encrypted = localStorage.getItem(key)return encrypted ? decrypt(encrypted) : null}
}
❓ 常见问题
1. 环境配置问题
Q: Python版本不兼容怎么办?
A: 确保使用Python 3.8+版本,推荐使用Python 3.11。可以使用pyenv管理多个Python版本。
Q: Node.js版本过低怎么办?
A: 确保使用Node.js 16+版本,推荐使用Node.js 18+。可以使用nvm管理Node.js版本。
Q: 数据库连接失败怎么办?
A: 检查数据库服务是否启动,确认连接参数是否正确,包括主机、端口、用户名、密码等。
2. 开发问题
Q: 前端热更新不生效怎么办?
A: 检查Vite配置,确认端口是否被占用,尝试重启开发服务器。
Q: API请求失败怎么办?
A: 检查后端服务是否启动,确认API地址配置是否正确,检查CORS配置。
Q: 数据库迁移失败怎么办?
A: 检查数据库连接,确认模型定义是否正确,可以尝试删除迁移文件重新生成。
3. 部署问题
Q: Docker容器启动失败怎么办?
A: 检查Docker配置,查看容器日志,确认端口是否被占用。
Q: 静态文件无法访问怎么办?
A: 检查Nginx配置,确认静态文件路径是否正确,检查文件权限。
Q: 数据库数据丢失怎么办?
A: 定期备份数据库,可以使用Docker volumes持久化数据。
4. 性能问题
Q: 页面加载速度慢怎么办?
A: 启用Gzip压缩,使用CDN加速,优化图片大小,启用缓存。
Q: 数据库查询慢怎么办?
A: 添加数据库索引,优化查询语句,使用缓存,考虑读写分离。
Q: 内存占用过高怎么办?
A: 检查内存泄漏,优化代码逻辑,增加服务器内存。
📞 技术支持
联系方式
- 项目地址: https://github.com/wangxiaozeze/Django_Pure
- 问题反馈: 请在GitHub Issues中提交问题
- 技术交流: 欢迎提交Pull Request
贡献指南
- Fork项目
- 创建功能分支
- 提交代码
- 创建Pull Request
- 等待代码审查
更新日志
- v1.0.0: 初始版本发布
- v1.1.0: 添加用户管理功能
- v1.2.0: 添加菜单管理功能
- v1.3.0: 添加角色管理功能
- v1.4.0: 优化UI界面,添加主题切换
🎉 总结
Django Pure Admin 是一个功能完整、技术先进的前后端分离管理系统,具有以下特点:
技术优势
- ✅ 现代化技术栈: Django 5.2 + Vue 3.4 + TypeScript
- ✅ 完整的功能体系: 用户、角色、权限、菜单管理
- ✅ 优秀的用户体验: 响应式设计、主题切换、国际化
- ✅ 良好的开发体验: 完整的开发文档、代码规范、测试覆盖
- ✅ 生产就绪: Docker部署、性能优化、安全防护
适用场景
- 🏢 企业内部系统: 员工管理、权限控制
- 🎓 教育管理系统: 学生、教师、课程管理
- 🏥 医疗管理系统: 患者、医生、科室管理
- 🏪 电商后台系统: 商品、订单、用户管理
- 🏭 生产管理系统: 设备、工艺、质量管理
未来规划
- 🚀 微服务架构: 支持服务拆分和独立部署
- 🤖 AI集成: 智能推荐、数据分析
- 📱 移动端支持: 响应式设计、PWA支持
- 🌐 多租户支持: SaaS化部署
- 🔐 增强安全: 双因子认证、审计日志
希望这个项目能够为您的开发工作提供帮助!如果您有任何问题或建议,欢迎与我们交流。
⭐ 如果这个项目对您有帮助,请给我一个关注!