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环境配置
bash
# 创建虚拟环境
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环境配置
bash
# 检查Node.js版本
node --version
npm --version
# 安装pnpm (推荐)
npm install -g pnpm
# 安装前端依赖
cd Frontend
pnpm install
3. 数据库环境配置
sql
-- 创建数据库
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)
sql
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)
sql
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)
sql
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. 数据模型设计
用户模型扩展
python
# Backend/App/models.py
from 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.name
class 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. 序列化器实现
python
# Backend/App/serializers.py
from rest_framework import serializers
from django.contrib.auth import authenticate
from .models import User, Menu, Notification
class 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'] = user
return attrs
else:
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 = User
fields = ('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 = Menu
fields = ('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. 视图实现
python
# Backend/App/views.py
from 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 LoginDevice
existing_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.user
return Response({
'code': 0,
'message': 'success',
'data': UserInfoSerializer(user).data
})
class MenuViewSet(viewsets.ModelViewSet):
"""菜单管理视图集"""
queryset = Menu.objects.all()
serializer_class = MenuSerializer
permission_classes = [permissions.IsAuthenticated]
@action(detail=False, methods=['get'], url_path='user-menus')
def user_menus(self, request):
"""获取当前用户的菜单"""
user = request.user
user_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接口层
typescript
// Frontend/src/api/auth.ts
import request from '@/utils/http'
export interface LoginParams {
username: string
password: string
device_info?: any
}
export interface UserInfo {
id: number
username: string
avatar?: string
realName?: string
phone?: string
email?: string
desc?: string
homePath?: string
roles?: string[]
}
export interface LoginResponse {
access_token: string
refresh_token: string
user_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. 状态管理
typescript
// Frontend/src/store/modules/user.ts
import { 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))
// 获取Token
const getToken = () => {
return localStorage.getItem('token') || ''
}
// 设置Token
const setToken = (newToken: string) => {
token.value = newToken
localStorage.setItem('token', newToken)
}
// 获取用户信息
const getUserInfo = async () => {
try {
const data = await authApi.getUserInfo()
userInfo.value = data
roles.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_info
roles.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 = null
roles.value = []
localStorage.removeItem('token')
localStorage.removeItem('refresh_token')
}
return {
// 状态
token,
userInfo,
roles,
// 计算属性
isLoggedIn,
hasRole,
// 方法
getToken,
setToken,
getUserInfo,
login,
logout,
resetUserInfo
}
})
4. 路由配置
typescript
// Frontend/src/router/index.ts
import { 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. 开发环境启动
后端启动
bash
# 进入后端目录
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
前端启动
bash
# 进入前端目录
cd Frontend
# 安装依赖
pnpm install
# 配置环境变量
# 修改 .env 文件中的API地址
# 启动开发服务器
pnpm dev
2. 生产环境部署
Docker部署方案
后端Dockerfile
dockerfile
# Backend/Dockerfile
FROM python:3.11-slim
WORKDIR /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
dockerfile
# Frontend/Dockerfile
FROM node:18-alpine as build
WORKDIR /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.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Docker Compose配置
yaml
# docker-compose.yml
version: '3.8'
services:
# MySQL数据库
db:
image: mysql:8.0
container_name: django_pure_db
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: django_pure
MYSQL_USER: django_pure
MYSQL_PASSWORD: your_password
volumes:
- mysql_data:/var/lib/mysql
- ./Backend/django_pure.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3306:3306"
networks:
- django_pure_network
# Redis缓存
redis:
image: redis:7-alpine
container_name: django_pure_redis
ports:
- "6379:6379"
networks:
- django_pure_network
# Django后端
backend:
build: ./Backend
container_name: django_pure_backend
environment:
- DEBUG=False
- DB_HOST=db
- DB_NAME=django_pure
- DB_USER=django_pure
- DB_PASSWORD=your_password
- REDIS_HOST=redis
- REDIS_PORT=6379
volumes:
- ./Backend/media:/app/media
- ./Backend/staticfiles:/app/staticfiles
depends_on:
- db
- redis
ports:
- "8000:8000"
networks:
- django_pure_network
# Vue前端
frontend:
build: ./Frontend
container_name: django_pure_frontend
ports:
- "80:80"
depends_on:
- backend
networks:
- django_pure_network
volumes:
mysql_data:
networks:
django_pure_network:
driver: bridge
Nginx配置
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. 部署步骤
bash
# 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代码规范
python
# 遵循PEP 8规范
# 使用Black进行代码格式化
# 使用isort进行导入排序
# 使用flake8进行代码检查
# 安装开发工具
pip install black isort flake8
# 格式化代码
black Backend/
isort Backend/
# 检查代码
flake8 Backend/
TypeScript代码规范
json
// 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工作流
bash
# 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. 测试策略
后端测试
python
# 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 status
User = 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'])
前端测试
typescript
// 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. 性能优化
后端优化
python
# 1. 数据库查询优化
# 使用select_related和prefetch_related
users = User.objects.select_related('profile').prefetch_related('groups').all()
# 2. 缓存策略
from django.core.cache import cache
def 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 Paginator
def get_paginated_users(page=1, page_size=20):
users = User.objects.all()
paginator = Paginator(users, page_size)
return paginator.get_page(page)
前端优化
typescript
// 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. 安全措施
后端安全
python
# 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保护
前端安全
typescript
// 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化部署
- 🔐 增强安全: 双因子认证、审计日志
希望这个项目能够为您的开发工作提供帮助!如果您有任何问题或建议,欢迎与我们交流。
⭐ 如果这个项目对您有帮助,请给我一个关注!