【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环境配置
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: 检查内存泄漏,优化代码逻辑,增加服务器内存。

📞 技术支持

联系方式

贡献指南

  1. Fork项目
  2. 创建功能分支
  3. 提交代码
  4. 创建Pull Request
  5. 等待代码审查

更新日志

  • 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化部署
  • 🔐 增强安全: 双因子认证、审计日志

希望这个项目能够为您的开发工作提供帮助!如果您有任何问题或建议,欢迎与我们交流。


⭐ 如果这个项目对您有帮助,请给我一个关注!

相关推荐
感哥24 分钟前
DRF 认证
python·django
今天练啥7 小时前
Django部署到服务器后无法获取到静态元素 The requested resource was not found on this server
django
爱学大树锯8 小时前
【Ruoyi 解密 - 08. 前端探秘1】------ 从“交互原理”到“开发逻辑”,后端也能看懂的前端实战指南
前端·elementui·vue
今天不要写bug19 小时前
antv x6实现封装拖拽流程图配置(适用于工单流程、审批流程应用场景)
前端·typescript·vue·流程图
修一呀1 天前
[后端快速搭建]基于 Django+DeepSeek API 快速搭建智能问答后端
后端·python·django
叫我阿柒啊1 天前
Java全栈开发面试实战:从基础到复杂场景的深度解析
java·数据库·spring boot·面试·vue·测试·全栈开发
菜鸟很沉1 天前
Vue3音频组件开发与使用指南
javascript·vue·音频组件
天籁晴空2 天前
vscode 配置 + androidStudio配置
vscode·uni-app·vue
lumi.3 天前
2.3零基础玩转uni-app轮播图:从入门到精通 (咸虾米总结)
java·开发语言·前端·vue.js·微信小程序·uni-app·vue