ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python+Vue+Django/Flask在线教育平台开发实战:核心模块与PyCharm全流程

Python+Vue+Django/Flask在线教育平台开发实战:核心模块与PyCharm全流程 1. 先聊聊这个项目的真实定位我最近在带一个在线教育平台的项目技术栈正好是标题里这套Python Vue Django/Flask PyCharm。很多人一看“在线教育”就以为要写视频点播、直播连麦、支付系统实际做下来才发现真正撑起一个教学平台日常运转的反而是“学习计划”和“师生互动”这两块。它们不炫技但数据结构、接口设计、前后端协作的坑一个都不少。这个项目适合谁参考如果你正在做课程管理系统、培训平台、或者任何带“学员-教师”角色的业务系统都可以把这套拆解拿过去改改。哪怕你只是刚学完 Django 基础、想找一个完整项目练手这篇文章也能帮你避开不少弯路。我会把整体设计思路、核心模块拆解、PyCharm 里的实操流程以及我实际踩过的坑都写出来尽量做到能直接照着复现。先说结论这个平台的核心不是视频而是学习计划和师生互动。视频只是内容载体真正让用户留下来的是“有计划地学”和“有人答疑”。2. 整体设计与技术选型背后的逻辑2.1 为什么是 Django Flask 双后端而不是只选一个很多新手会纠结标题里两个后端框架都用是不是冗余我实际开发后的感受是这两个框架在这个项目里各有各的位置用了反而更顺手。Django 负责主业务系统。用户管理、课程表、学习计划、作业提交、成绩记录这些都属于强业务逻辑、强数据关联的部分。Django 自带 ORM、Admin 后台、迁移机制我写学习计划的状态流转、师生互动的消息关联开发效率非常高。特别是 Admin 后台给运营人员做课程上下架和学员管理几乎是零成本。Flask 负责轻量级辅助服务。比如课节视频的播放进度上报、签到打卡、消息已读回执这类高频但逻辑简单的接口。Flask 写起来轻路由清晰部署时单独起一个服务不会因为 Django 的中间件和认证体系拖慢响应。还有一个实际原因项目里有一个“每日学习打卡”的统计接口需要对接第三方短信通知这个逻辑如果塞进 Django 主工程耦合会很重放在 Flask 独立服务里就舒服很多。有人会问为什么不直接上 FastAPI我在对比 Flask 和 FastAPI 时考虑过性能问题但这个平台的瓶颈根本不在接口吞吐量而在开发协作的熟悉度。团队里有人对 Flask 更熟而且 Flask 生态里的扩展足够覆盖需求。FastAPI 的异步优势在这个场景里用不上反而徒增学习成本。技术选型不是选最潮的是选团队能用好的。2.2 Vue 在项目里承担的角色前端用 Vue没有用 React原因很直接Vue 的中文生态好模板语法对做后端出身的开发者友好而且和 Django/Flask 搭配的教程资料多遇到问题容易搜到答案。在线教育平台的前端其实不需要太复杂的交互。主要页面是课程列表、课程详情、学习计划看板、问答社区、个人中心。Vue 的组件化很适合这类页面复用比如课程卡片组件、评论列表组件、计划进度条组件写一次到处用避免重复劳动。特别说一下学习计划看板前端。我用的 Vue Router 做页面路由每个学员登录后进入“我的学习计划”里面展示计划进度、待学课程、已完成课时、作业截止日期。这块的交互逻辑不复杂但状态管理要注意学员切换课程、打卡、提交作业后页面的进度数据要实时刷新。我一开始用组件内 props 传递后来发现多层级组件传值太痛苦干脆上了 Vuex把用户信息和学习进度放到全局 store 里前后端交互清爽了很多。3. 学习计划模块看起来简单做起来全是细节3.1 数据模型设计的关键点学习计划这个模块第一版我设计得过于简单就一张表用户 ID、课程 ID、计划开始时间、计划结束时间。结果跑了一个星期就发现不够用。学员的需求不是“给我一个起止时间”而是“我要知道今天学什么、学了没有、下一步学什么”。所以后来我重新拆了数据模型核心是四张表课程表课程基础信息包含课程标题、封面图、分类、教师 ID。学习计划表计划名称、所属学员 ID、关联课程 ID、开始日期、结束日期、整体状态未开始/进行中/已完成/已逾期。计划任务表这是最关键的。一条计划下拆出多个任务每个任务对应一个课时包含计划日期、课时 ID、是否完成、完成时间、备注。学习记录表记录每次学习行为的明细比如看了哪个视频、看了多少分钟、最后一次学习时间。第二张表纯粹是给后台统计用的。学习计划页面展示进度时前端只需要查计划任务表里“已完成任务数 / 总任务数”而不用去关联视频播放记录查询效率高很多。这套模型设计好之后我才发现之前踩的坑在哪计划任务表必须冗余课时标题和教师 ID。因为学员在前端看计划时要显示每个任务的课时名和授课老师如果每次都要 JOIN 课程表再 JOIN 课时表列表接口会很慢。冗余虽然不符合彻底的三范式但在这个场景下性价比极高。3.2 学习计划的进度计算逻辑进度计算是最容易出 bug 的地方。我最初写了个接口计划进度 已完成任务数 / 总任务数 x 100。听起来没问题但用户反馈说“我看了视频为什么不算完成”因为“看了视频”和“完成课时”是两回事。我后来引入了“三态完成判断”当学习记录表里视频播放进度超过 80%自动把该课时的任务标记为“学完”。如果作业已提交也视为完成因为有些课时没有视频只有作业。如果两个条件都满足状态自然是完成不重复计数。进度接口的计算逻辑变成先查计划任务表得到任务列表再查学习记录表和作业提交表确认每个任务的完成状态最后统计完成率。炸一看两次查询很费但加上 Django ORM 的select_related和prefetch_related一条查询就能把关联数据带出来响应时间基本在 50ms 以内。一个容易忽略的细节计划逾期判断。如果计划结束日期小于当前日期但任务没有全部完成计划状态要从“进行中”改成“已逾期”。这个状态不能只靠前端判断Django 端要写个定时任务每天凌晨跑一次把逾期计划批量更新。不做这一步学员的看板会一直显示“进行中”等到结课才发现进度没达标运营就得背锅。3.3 日历视图与任务提醒的实现学习计划做出来之后学员反馈最多的是“我不知道今天该学什么”。所以我又加了日视图按日期展示每天的学习任务类似日历那种。前端用 Vue 写了一个简单但够用的日历组件不需要引第三方库。数据接口是根据当前日期查计划任务表返回当天的任务列表。如果当天没任务前端显示“今日无安排可以复习之前的内容”。任务提醒我用的方法是Django 的 Celery 定时任务 站内信通知。每天上午 8 点检查当天有学习任务的用户给他们发送站内消息。站内消息表很简单接收者 ID、消息类型、关联计划 ID、内容、是否已读、创建时间。这样既不需要手机推送省掉接入极光推送的成本又能让学员一登录就看到“今天有 2 个学习任务”。为什么不用短信因为短信费太贵平台刚起步每天活跃用户就几百人几条短信还能承受规模大了再说。做项目得算成本账不能为了功能而功能。4. 师生互动交流模块别把论坛做成聊天室4.1 互动场景拆解师生互动听起来很宽泛我接到需求时也是一头雾水。后来和产品聊完拆成三个具体场景课程问答学员在学习某个课时时有问题可以针对该课时发起提问教师或助教回答。作业点评学员提交作业后教师给出文字评价和打分学员可以看到点评记录。站内私信一对一的实时信息沟通主要用于催缴作业、答疑、约辅导时间。这三个场景的交互模型完全不同如果混在一张表里后面做查询和分析都会很痛苦。我的做法是建立三种基础模型问题表问题标题、问题内容、所属课时 ID、提问者 ID、状态待回答/已回答/已关闭、创建时间。回答表所属问题 ID、回答者 ID、回答内容、点赞数、是否采纳、创建时间。私信表发送者 ID、接收者 ID、消息内容、会话 ID、是否已读、创建时间。这里最关键的字段是会话 ID。私信功能如果每次都查“我和某人的私信列表”用 SQL 也能实现但会话数量大了之后会特别慢。在私信表里维护一个会话 ID发送时先查当前用户和对方是否已有会话没有就新建有就直接往会话里追加消息。列表页只需要按会话 ID 分组展示最近一条消息即可。4.2 问答流程的状态机设计课程问答不是简单的发帖回帖它有明确的业务状态。我定义了一个状态机待回答学员提交问题后的初始状态。已回答教师或助教回复后状态更新。已关闭提问者确认问题解决或超过 7 天无人回复系统自动关闭。被采纳提问者采纳了某个回答问题结贴。实现这个状态机Django 里我用的不是硬编码 if-else而是单独写了一个QUESTION_STATUS常量类然后在 Question 模型里加了close_question()和mark_as_answered()方法。这样业务逻辑凝固在模型里视图层只调用方法不会出现“状态判断散落在接口各处”的维护噩梦。另外问题是关联课时还是关联课程我一开始关联课时后来发现不对。学员问问题的时候往往是“整个课程我不明白”而不是“这一个视频我没看懂”。所以问题表里同时保留课程 ID 和课时 ID课时 ID 可以为空。查询列表时如果课时 ID 不为空就显示“来自课时《XXX》”为空则显示“来自课程《XXX》”。灵活很多。4.3 私信模块的实时性选择做私信的时候团队里有人提议上 WebSocket实现真正的“实时聊天”。但我权衡了一下最终选择轮询。原因很简单教育平台的私信和微信不一样信息量少用户也不需要毫秒级回复。轮询每 5 秒拉取一次新消息对服务器压力很小而且技术实现简单Django 的视图函数直接支持。WebSocket 要引入 Channels改造 ASGI 部署还要处理长连接断线重连当前团队水平做下来得不偿失。轮询接口的设计也有讲究。不是每次返回所有私信而是带一个last_message_id参数前端只拉取大于这个 ID 的新消息。这是一个非常朴素的增量拉取方案但实用响应体很小网络开销低。如果后续用户量上来了我可能会把私信模块单独拆成一个小服务用 WebSocket 或者 SSE 做推送。但目前这版够用先跑起来再说。5. PyCharm 里从零搭建项目的完整流程5.1 虚拟环境与基础安装很多新手在 PyCharm 里建 Django 项目第一步就搞混了。注意PyCharm 新建项目时选择虚拟环境不要直接用全局 Python 环境。虚拟环境能隔离不同项目的依赖版本不然你升级了某个包其他项目全崩。我的操作步骤是在 PyCharm 的New Project里选Pure PythonLocation选择项目目录Interpreter选择New environment using Virtualenv。创建完成后打开终端PyCharm 自带的 Terminal执行pip install django和pip install flask。确认版本python -m django --version。我用的 Django 4.2这个版本对 Python 3.8 兼容性好而且自带了一些新特性适合教学项目。这里有个坑PyCharm 的默认虚拟环境路径如果包含中文pip 安装某些包会失败。比如D:\学习项目\在线教育平台中文路径会导致编译型库如Pillow安装时报编码错误。我建议项目路径全用英文或者顶多用数字前缀比如D:\edu-platform。这不是玄学是我踩过之后查源码才发现的问题。5.2 Django 项目与 App 的创建顺序项目骨架我按下面的顺序创建在终端执行django-admin startproject edu_platform .。注意最后的那个点表示在当前目录创建项目不要自动套一层同名目录。创建主 Apppython manage.py startapp courses。这个 App 负责课程和学习计划。创建第二个 Apppython manage.py startapp interaction。这个 App 负责师生问答和私信。创建第三个 Apppython manage.py startapp users。负责用户和角色管理。为什么拆成三个 App因为 Django 的最佳实践是一个 App 负责一个业务域而不是把所有模型塞进一个 App。拆开之后以后要扩展功能比如加一个“考试”模块直接新建 App不影响现有代码。创建完后还要在settings.py的INSTALLED_APPS里注册这三个 App不然迁移表结构时 Django 找不到模型。这一步新手最容易漏漏了之后makemigrations会提示“No changes detected”然后一脸懵。5.3 Vue 前端工程与 Django 的联动前端我放在项目根目录下的frontend文件夹里。用 Vue CLI 创建还是 Vite 创建我选的是 Vite。Vite 启动快热更新响应快开发体验比 webpack 时代好太多。如果小白用 Vue CLI 也能接受但 Vite 已经是主流。创建命令npm create vitelatest frontend -- --template vue cd frontend npm install npm run dev开发环境里前端在localhost:5173Django 在localhost:8000。跨域问题必须处理。我在 Django 的settings.py里安装了django-cors-headers并把CORS_ALLOWED_ORIGINS配置为前端地址。注意只配置开发环境的跨域生产环境部署时后端的接口和前端页面最好是同一个域名或者用 Nginx 反向代理避免跨域带来的安全风险。前后端接口联调用的是 Axios。我在frontend/src/api目录里给每个业务模块建了一个文件。比如course.js导出getCourseList、getCourseDetail、createStudyPlan等方法每个方法内部封装axios.get或axios.post。这样做的好处是页面组件里不需要直接写 URL改接口地址时只改一个文件。5.4 用 PyCharm 运行和管理项目PyCharm 里我配置了两个运行配置Django 项目运行类型选 Django Server指定settings.py的位置端口保持 8000。前端项目运行类型选 JavaScript Debug 或直接在终端跑npm run dev。我更推荐在 PyCharm 终端里跑方便看日志。调试时我习惯同时开两个终端窗口一个跑 Django一个跑 Vue。PyCharm 的Run工具窗口可以多标签管理不用来回切。有一点必须提醒PyCharm 的 Django 模板调试很强大但如果你的前端是 Vue 写的Django 模板里尽量不要混着写 Vue 语法。{{ }}在 Django 模板和 Vue 里都是插值表达式混用会冲突。我的做法是Django 只负责接口 API页面完全由 Vue 渲染后端不返回 HTML 模板。这也是现在前后端分离的主流做法。6. 实操中的高频问题与排查技巧实录6.1 Django 删除对象时外键约束报错做课程删除功能时我遇到一个经典报错ProtectedForeignKey或RestrictedForeignKey错误意思是删除课程时有相关学习计划引用它数据库拒绝了操作。我当时的第一反应是直接改外键的on_deletemodels.CASCADE这样删除课程时关联数据一起删。但这是错误的做法。学习计划是学员的历史记录如果课程被删除计划里的课程信息不应该一起消失而应该保留只是标记为“课程已下架”。正确做法是把外键的on_delete设为SET_NULL并且让关联字段允许为空course models.ForeignKey( Course, on_deletemodels.SET_NULL, nullTrue, blankTrue, related_namestudy_plans )然后删除课程的接口里先批量把关联计划的状态改为“已失效”再执行删除。这样既不会报外键错误也保留了计划的历史记录学员端仍然能看到自己学过的内容。6.2 Vue 路由切换后页面数据不刷新我在做学习计划详情页时发现一个奇怪现象从计划 A 切换到计划 BURL 变了但页面上显示的还是计划 A 的数据。原因很简单Vue Router 复用了同一个组件实例created钩子只在首次加载时执行后续路由参数变化不会重新触发。解决方法是监听路由变化watch: { $route.params.id: { handler() { this.fetchPlanDetail() }, immediate: true } }这里immediate: true很关键它让组件初始加载时也执行一次避免了额外的created钩子。踩过这个坑之后我再写带路由参数的详情页都会习惯性地用watch而不是created。6.3 Flask 部署时静态文件 404在一个辅助服务里我需要 Flask 返回一个简单的 HTML 报告页面。本地运行正常部署到云服务器后静态文件CSS、JS全部 404。查了一圈发现 Flask 默认只在开发服务器下处理静态文件生产环境需要自己配 Nginx 或使用send_from_directory。我的方案是把这个服务完全做成接口型不回 HTML所有数据以 JSON 返回。前端 Vue 直接调接口渲染页面绕掉了 Flask 静态文件的问题。如果你的场景必须由 Flask 返回页面那么要在配置里指定static_folder并确保 Nginx 指向正确路径。但这个项目里没必要让 Flask 承担页面渲染。6.4 PyCharm 里导入已存在的 Django 项目有朋友问我“在 PyCharm 里怎样导入已建立好的基于 Django 的信息系统”这个问题很常见。步骤其实不多File - Open选择项目目录。PyCharm 识别到项目里有requirements.txt会提示安装依赖点确认。如果没提示进入Settings - Project - Python Interpreter选择项目已有的虚拟环境或者新建虚拟环境后pip install -r requirements.txt。配置 Django 支持Settings - Languages Frameworks - Django勾选Enable Django support指定settings.py路径。然后运行配置里新建一个 Django Server 类型的配置就能跑起来了。这里面最隐性的坑是虚拟环境路径不对。如果项目是从别人那里拷贝过来的原虚拟环境路径在别人机器上导入后 PyCharm 会提示 interpreter 不存在。解决办法是新建虚拟环境再重新安装依赖。别尝试复用别人的 venv 目录Python 虚拟环境对路径很敏感。7. 关于部署与后续扩展的一点建议部署这块我可以分享一个简单可靠的方案Django 和 Flask 分别跑在不同端口前端 Vue 打包成静态文件后用 Nginx 托管Nginx 再把/api开头的请求反向代理到 Django把/flask开头的请求代理到 Flask。这个架构图在脑子里非常清晰虽然我没画出来但实操起来也就三步前端npm run build生成dist目录。把dist上传到服务器配置 Nginx root 指向它。Django 用 Gunicorn 启动Flask 用 gunicorn 或 uwsgi 启动Nginx 做代理。部署到这一步时你才会意识到为什么当初要把轻量功能放到 FlaskDjango 服务出问题时打卡和私信这些辅助功能还能正常运转不至于整个平台瘫掉。这是我在一次服务器重启之后发现的价值。最后说点实在的这套项目做完我的体会是在线教育平台真正难的不是技术而是学习计划的数据建模和师生互动的状态流转。Vue 和 Django 的知识点多且杂但真正到业务落地时考验的是你把业务拆成数据模型、把交互拆成接口的能力。PyCharm 只是工具别在 IDE 配置上浪费太多精力把核心逻辑想清楚项目就成功了一半。如果你也在做类似的平台欢迎按上面的思路试试。尤其是计划任务表那套设计建议第一版就做进去不然后面改表结构会非常痛苦。
返回列表