简介这是一套面向计算机专业本科生的毕业设计级个人理财系统完整实现基于PythonDjango后端与Vue前端构建解决个人收支管理、财务规划与多角色协同监控等实际需求适用于课程设计、毕设参考及全栈开发能力训练。资源共383个文件涵盖49个核心Python后端逻辑文件、40个Vue组件页面、28个PNG图标与界面素材、18个JS交互脚本、2个SQL数据库脚本及3个MP4演示视频另有安装/运行/构建等配套BAT批处理脚本压缩包仅18.9MB轻量易部署。已有428人学习下载内容完整度高包含可直接运行的源码、MySQL建库建表脚本、结构清晰的毕业论文含需求分析、ER图、接口设计、全流程操作演示视频以及含BreadCrumbs、IndexHeader等模块化Vue组件的前端工程结构便于理解前后端分离架构与权限分层设计。1. 一个能跑通、能答辩、能改需求的个人理财系统为什么 Django Vue 组合在毕业设计里既稳又出彩你不是在造火箭而是在交一份能通过答辩、能现场演示、能应对老师“再加个导出 Excel 功能”的毕业设计。这个标题里的「个人理财系统」不是 SaaS 产品而是典型的数据驱动型 Web 应用用户登录后管理收支分类、录入每笔账单、查看月度饼图、筛选时间段流水、导出 CSV——所有操作背后是清晰的 CRUD 逻辑、可验证的业务规则比如支出不能为负、以及必须落地的前后端分离结构。选 Python Django Vue MySQL不是跟风而是因为 Django 提供开箱即用的 Admin 后台、ORM 映射和表单校验Vue 能快速响应数据变化实现动态图表与实时过滤MySQL 则保证本地部署零依赖、ER 图直观、SQL 查询可调试。这套组合让代码量可控、调试路径明确、答辩时能指着数据库表说“这里存的是分类层级”也能对着浏览器 Network 面板解释“这笔请求走的是 /api/transactions/ 接口”。它适合计算机/信管/电商等专业学生——不需要分布式经验但要求你真正理解请求怎么从点击按钮走到数据库写入。2. 搭建最小可运行骨架Django 后端服务与 Vue 前端容器的双向打通2.1 初始化 Django 项目并配置 MySQL 数据库连接毕业设计阶段最怕环境崩、版本冲突。推荐使用 Python 3.9–3.11避开 Django 5.x 对 SQLite 的默认升级陷阱Django 版本锁定在 4.2 LTS长期支持文档全兼容性好。创建虚拟环境后执行python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install django4.2.11 mysqlclient2.2.4 django-admin startproject finance_project .修改settings.py中的DATABASES配置必须显式指定 MySQL 驱动和字符集DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: finance_db, # 数据库名需提前在 MySQL 中 CREATE DATABASE USER: root, PASSWORD: your_password, # 生产环境严禁明文此处仅用于本地开发 HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, # 关键支持 emoji 和四字节 UTF-8 init_command: SET sql_modeSTRICT_TRANS_TABLES, }, } }提示mysqlclient是 Django 官方推荐的 MySQL 驱动比 PyMySQL 更稳定若pip install mysqlclient报错Windows 用户需先安装 Microsoft Visual C Build ToolsmacOS 用户用brew install mysql-client并设置export PATH/opt/homebrew/opt/mysql-client/bin:$PATH。2.2 定义核心模型账户、分类、账单的 ER 关系落地个人理财系统的核心实体只有三个用户账户User 扩展、收支分类Category、具体账单Transaction。Django ORM 要求字段语义清晰、外键约束明确、查询高效。在finance_app/models.py中定义from django.db import models from django.contrib.auth.models import User class Category(models.Model): name models.CharField(max_length50, verbose_name分类名称) type models.CharField( max_length10, choices[(income, 收入), (expense, 支出)], verbose_name类型 ) parent models.ForeignKey( self, on_deletemodels.CASCADE, nullTrue, blankTrue, related_namechildren, verbose_name父分类 ) class Meta: verbose_name 收支分类 verbose_name_plural 收支分类 class Transaction(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE, verbose_name所属用户) category models.ForeignKey(Category, on_deletemodels.PROTECT, verbose_name分类) # PROTECT 防删被引用分类 amount models.DecimalField(max_digits12, decimal_places2, verbose_name金额) date models.DateField(verbose_name发生日期) description models.CharField(max_length200, blankTrue, verbose_name备注) class Meta: verbose_name 账单记录 verbose_name_plural 账单记录 ordering [-date] # 默认按日期倒序执行迁移命令生成表结构python manage.py makemigrations python manage.py migrate python manage.py createsuperuser # 创建管理员账号用于访问 /admin/此时在 MySQL 中执行SHOW CREATE TABLE finance_app_transaction;你会看到user_id和category_id字段已自动添加外键约束date字段类型为dateamount为decimal(12,2)—— 这正是毕业设计答辩时可展示的“数据库设计合理性”。2.3 Vue CLI 创建前端项目并配置跨域代理Vue 项目不嵌入 Django 模板而是独立运行于http://localhost:8080Django API 服务运行于http://localhost:8000。为避免浏览器 CORS 阻止请求必须在 Vue 项目根目录下创建vue.config.js// vue.config.js module.exports { devServer: { proxy: { /api: { target: http://127.0.0.1:8000, changeOrigin: true, pathRewrite: { ^/api: /api // 保持 API 路径一致 } } } } }然后初始化 Vue 项目推荐 Vue 3 Composition APInpm create vuelatest # 选择 TypeScript、Router、Pinia、Vitest按需 cd frontend npm install npm run dev在src/api/index.ts中封装 Axios 实例统一处理请求头和错误import axios from axios const api axios.create({ baseURL: /api, // 开发时走 proxy生产部署需替换为真实域名 timeout: 10000, }) // 请求拦截自动携带 token后续登录后启用 api.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Token ${token} } return config }) export default api此时打开http://localhost:8080控制台无跨域报错Network 面板能看到/api/transactions/请求成功返回 JSON —— 前后端通信链路已通。3. 实现核心功能闭环从账单录入到图表渲染的端到端流程3.1 Django REST Framework 构建标准 API 接口毕业设计不需复杂权限体系但 API 必须符合 REST 规范、有清晰文档、能被 Postman 验证。安装djangorestframework并注册应用pip install djangorestframework3.14.0在finance_app/views.py中编写基于ModelViewSet的视图from rest_framework import viewsets, permissions from rest_framework.decorators import action from rest_framework.response import Response from .models import Transaction, Category from .serializers import TransactionSerializer, CategorySerializer class TransactionViewSet(viewsets.ModelViewSet): serializer_class TransactionSerializer permission_classes [permissions.IsAuthenticated] def get_queryset(self): return Transaction.objects.filter(userself.request.user) def perform_create(self, serializer): serializer.save(userself.request.user) # 强制绑定当前用户 action(detailFalse, methods[get]) def summary(self, request): 获取当月收支汇总 from django.db.models import Sum from datetime import date today date.today() month_start today.replace(day1) data Transaction.objects.filter( userrequest.user, date__gtemonth_start ).values(category__type).annotate(totalSum(amount)) return Response(list(data)) class CategoryViewSet(viewsets.ReadOnlyModelViewSet): queryset Category.objects.all() serializer_class CategorySerializer permission_classes [permissions.IsAuthenticated]对应serializers.py定义字段校验规则from rest_framework import serializers from .models import Transaction, Category class CategorySerializer(serializers.ModelSerializer): class Meta: model Category fields [id, name, type, parent] class TransactionSerializer(serializers.ModelSerializer): class Meta: model Transaction fields [id, category, amount, date, description] extra_kwargs { amount: {min_value: 0.01}, # 支出/收入至少 1 分钱 date: {required: True} }最后在urls.py中注册路由from django.urls import path, include from rest_framework.routers import DefaultRouter from finance_app import views router DefaultRouter() router.register(rtransactions, views.TransactionViewSet) router.register(rcategories, views.CategoryViewSet) urlpatterns [ path(api/, include(router.urls)), path(admin/, admin.site.urls), ]启动服务后访问http://127.0.0.1:8000/api/transactions/即可看到分页 JSON 数据POST /api/transactions/可创建新账单 —— 这是答辩时演示“接口可用性”的直接证据。3.2 Vue 页面实现账单列表、新增表单与 ECharts 动态图表Vue 端使用vue-router实现页面跳转pinia管理全局状态如当前用户、分类列表。在src/views/TransactionList.vue中template div classtransaction-list h2账单列表/h2 button clickshowAddForm true新增账单/button div v-ifshowAddForm classadd-form input v-modelnewTransaction.category placeholder分类ID typenumber / input v-modelnewTransaction.amount placeholder金额 typenumber step0.01 / input v-modelnewTransaction.date typedate / input v-modelnewTransaction.description placeholder备注 / button clickaddTransaction提交/button button clickshowAddForm false取消/button /div ul li v-fort in transactions :keyt.id {{ t.date }} {{ t.description }} ¥{{ t.amount }} /li /ul div refchartRef stylewidth: 600px; height: 400px;/div /div /template script setup langts import { ref, onMounted } from vue import { useTransactionStore } from /stores/transaction import * as echarts from echarts const store useTransactionStore() const chartRef refHTMLElement | null(null) const showAddForm ref(false) const newTransaction ref({ category: 1, amount: 0, date: new Date().toISOString().split(T)[0], description: }) const addTransaction async () { await store.addTransaction(newTransaction.value) showAddForm.value false newTransaction.value { category: 1, amount: 0, date: new Date().toISOString().split(T)[0], description: } } onMounted(() { store.fetchTransactions() // 初始化 ECharts 图表 if (chartRef.value) { const chart echarts.init(chartRef.value) chart.setOption({ title: { text: 本月收支分布 }, tooltip: {}, series: [{ type: pie, data: store.summary.map(item ({ name: item.category__type income ? 收入 : 支出, value: item.total })) }] }) } }) /script关键点在于useTransactionStore封装了对/api/transactions/的 GET/POST 请求store.summary是从GET /api/transactions/summary/获取的聚合数据ECharts 图表在onMounted中初始化避免 SSR 渲染失败表单输入绑定v-model提交调用store.addTransaction()—— 全流程可调试、可打断点。3.3 数据库 ER 图生成与答辩材料准备毕业论文中“数据库设计”章节必须附 ER 图。不要手绘用 Django 自带工具生成 PlantUML 或 Mermaid 源码pip install django-extensions graphviz # 在 settings.py 中添加 INSTALLED_APPS [django_extensions] python manage.py graph_models finance_app -o er_diagram.png该命令会生成 PNG 格式 ER 图清晰显示User → Transaction一对多、Category → Transaction多对一、Category → Category自关联三类关系。答辩 PPT 中可截图此图并标注“Transaction.amount使用DecimalField确保财务精度Category.parent设置on_deletemodels.CASCADE实现分类树级联删除”。同时导出 MySQL 数据库结构供论文附录mysqldump -u root -p --no-data finance_db finance_db_schema.sql该 SQL 文件包含CREATE TABLE语句、FOREIGN KEY定义、CHARSETutf8mb4声明 —— 直接粘贴进论文“数据库物理设计”小节比文字描述更可信。4. 生产部署与性能调优让系统在答辩现场稳定运行4.1 使用 Gunicorn Nginx 部署 Django 后端本地runserver不可用于答辩演示。Linux 环境或 Windows WSL下用 Gunicorn 启动 WSGI 应用pip install gunicorn gunicorn finance_project.wsgi:application --bind 127.0.0.1:8000 --workers 2 --timeout 30Nginx 作为反向代理配置/etc/nginx/sites-available/financeupstream django_app { server 127.0.0.1:8000; } server { listen 80; server_name localhost; location /static/ { alias /path/to/finance_project/staticfiles/; # collectstatic 后路径 } location / { proxy_pass http://django_app; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }启用配置后重启 Nginx访问http://localhost/api/transactions/应返回 JSON —— 此时后端已脱离开发服务器具备生产级稳定性。4.2 Vue 项目构建与静态资源集成Vue 项目构建输出静态文件由 Django 的whitenoise或 Nginx 直接托管cd frontend npm run build # 输出到 dist/ 目录将dist/内容复制到 Django 项目static/目录下或在 Nginx 中配置location / { root /path/to/frontend/dist; try_files $uri $uri/ /index.html; }关键参数说明--workers 2Gunicorn 工作进程数毕业设计场景 2 个足够避免内存溢出--timeout 30请求超时设为 30 秒防止慢查询阻塞proxy_set_header系列确保 Django 能正确读取客户端 IP 和 Hosttry_filesVue Router 的 history 模式必需否则刷新页面 404。4.3 关键性能优化项减少答辩现场卡顿答辩演示最怕页面加载慢、图表渲染卡、列表翻页延迟。三项必做优化优化项操作验证方式数据库查询优化在TransactionViewSet.get_queryset()中添加.select_related(category)避免 N1 查询Django Debug Toolbar 查看 SQL 数量是否从 10 降至 1API 响应压缩安装django-compressor启用GZIP中间件浏览器 Network 面板对比Content-Encoding: gzip前后大小ECharts 懒加载图表容器添加v-iftransactions.length确保数据加载完成后再初始化控制台无Cannot initialize ECharts报错例如在视图中优化查询def get_queryset(self): return Transaction.objects.filter( userself.request.user ).select_related(category) # 预加载分类信息这样获取 20 条账单时SQL 从 21 条1 条主表 20 条分类降为 1 条 JOIN 查询页面秒开。5. 答辩高频问题预演与代码可维护性加固5.1 预判导师三类问题及应答要点毕业答辩中导师提问往往围绕“为什么这么做”而非“怎么做”。以下是三类高频问题及技术级应答逻辑Q1为什么用 MySQL 而不用 SQLite→ 回答聚焦可扩展性与规范性“SQLite 适合原型验证但毕业设计需体现数据库选型能力。MySQL 支持多用户并发、事务隔离级别如READ COMMITTED、外键约束强制关联完整性且mysqldump导出结构便于论文附录呈现。答辩现场演示SELECT ... FOR UPDATE加锁操作可证明对数据库事务的理解。”Q2Vue 和 Django 如何保证数据一致性比如删除分类时关联账单怎么处理→ 指向具体代码“Django 模型中category models.ForeignKey(..., on_deletemodels.PROTECT)删除被引用分类时抛出ProtectedError前端在分类列表页禁用删除按钮或弹窗提示‘存在关联账单’。这种服务端强约束 前端友好提示比纯前端校验更可靠。”Q3如果要增加‘预算管理’模块架构上如何扩展→ 展示设计思维“新增Budget模型关联Category和User字段含amount、start_date、end_dateAPI 增加/api/budgets/端点前端在账单录入页增加‘是否超预算’实时校验逻辑。所有改动仅新增文件不修改现有Transaction逻辑 —— 符合单一职责原则。”5.2 代码可维护性加固为答辩后修改留出空间导师常要求“现场加个功能”代码结构决定修改成本。以下三点让系统易扩展API 版本化在urls.py中将路由改为path(api/v1/, include(router.urls))未来新增 v2 接口不破坏旧版环境配置分离创建settings/base.py、settings/dev.py、settings/prod.pyDEBUG、SECRET_KEY、数据库密码均从环境变量读取业务逻辑抽离将金额校验、分类树生成等逻辑移至finance_app/services.py视图只负责请求/响应转换。例如分类树生成服务# finance_app/services.py def build_category_tree(user): 构建用户可用的分类树含收入/支出根节点 roots Category.objects.filter(parentNone) tree [] for root in roots: tree.append({ id: root.id, name: root.name, type: root.type, children: _get_children(root) }) return tree def _get_children(node): children node.children.all() return [{ id: c.id, name: c.name, type: c.type, children: _get_children(c) } for c in children]视图中调用build_category_tree(request.user)而非直接查库 —— 修改树形逻辑只需动services.py不影响 API 层。5.3 一键复现脚本让答辩前 1 小时重装环境不慌写一个setup_dev.shLinux/macOS或setup_dev.batWindows包含所有初始化步骤#!/bin/bash # setup_dev.sh echo 正在初始化开发环境... python -m venv venv source venv/bin/activate pip install -r requirements.txt python manage.py migrate python manage.py loaddata initial_categories.json # 预置常用分类 echo 环境初始化完成执行 python manage.py runserver 启动后端配套requirements.txt明确版本Django4.2.11 mysqlclient2.2.4 djangorestframework3.14.0 django-crispy-forms2.0答辩前运行此脚本5 分钟内重建完整环境 —— 这比临时 debug 任何报错都更让人安心。本文还有配套的精品资源点击获取