首页 / 资讯中心 / 文章详情

Flask+Vue前后端分离开发校园兼职系统实战指南

Flask+Vue前后端分离开发校园兼职系统实战指南 ★ FEATURED ARTICLE
最近帮一个学弟把这套基于 Flask 的大学生校园兼职系统完整跑了一遍前端用 Vue整个开发过程基本都在 PyCharm 里完成。说实话这类题目在高校里的出现频率非常高因为它同时覆盖了账号体系、信息发布、流程审批和角色权限这些经典模块。但大多数同学卡住的点不在写代码而在技术选型混乱——标题里挂 Flask 又挂 Django后面还跟着 Vue 和 PyCharm一上来就不知道谁才是主线。这篇文章我就按自己实际带项目的顺序来拆需求怎么梳理、Flask 和 Django 在什么情况下取舍、数据库怎么建、接口怎么写、Vue 页面怎么接以及 PyCharm 里那些能救命的调试技巧。适合正在做课程设计、毕业设计或者想自己完整做一个前后端分离项目的同学直接参考。1. 项目定位与技术选型1.1 从校园兼职痛点反推功能需求校园兼职这个场景本质上是一个双向信息匹配问题。学生这边想知道哪里有真实可靠的兼职薪资怎么算做完能不能按时结雇主那边想快速招到有空闲时间的学生并且清楚这个学生到底有没有申请、谁能来面试平台管理侧还要保证信息不泛滥发布内容需要审核账号要有分层。如果跳过分析直接写代码大概率写着写着就不知道自己为什么要写这个接口。我习惯把每个角色能做的事先列出来再反推系统需要哪些模块。学生角色的核心诉求是注册登录、浏览兼职、按关键词搜索、申请心仪岗位、查看申请进度、维护个人资料。雇主角色的核心诉求是注册登录、发布兼职岗位、查看收到的申请、接受或拒绝学生、对完成的工作进行结算标记。管理员角色的核心诉求是审核职位是否合规、管理异常用户、查看平台整体的兼职数据。把这些需求合并一下系统的功能模块就非常清晰了账号认证模块、兼职信息模块、在线申请模块、审核管理模块外加一个用于提醒的站内消息模块。这个颗粒度对于课程设计或者毕业设计来说刚好不会因为功能太少显得单薄也不会因为功能太多导致工期失控。1.2 Flask 与 Django 如何取舍以及 Vue 的角色项目标题里同时出现 Flask 和 Django其实是很常见的现象因为很多同学在选型阶段会把两个框架的关键词一起写进去然后陷入纠结。我给一个比较明确的判断如果项目定位写的是“基于 Flask”那主线就走 FlaskDjango 可以当作对比方案来理解而不是必须同时用两套框架。为什么这么选Flask 的特点就是轻、薄、灵活。整个框架的核心代码量不大你可以从一个请求进来开始逐步跟踪它怎么被路由、怎么进入视图函数、怎么返回 JSON。这个过程对正在学习后端原理的同学来说非常友好。Django 的优势则是“全家桶”自带 Admin 后台、ORM、用户认证开箱即用。但它的“重”主要体现在工程结构和中间件体系上新手很容易被这些东西干扰搞不清楚自己写的代码到底挂在哪里。前端选 Vue是因为 Vue 的渐进式设计让页面拆分非常顺畅配合 Vue Router 做页面跳转、Axios 发起 HTTP 请求是当前前后端分离项目里非常成熟的组合。开发工具选择 PyCharm主要看中的是它的调试能力、虚拟环境管理和数据库面板集成这一块我在第 6 章会详细展开。2. 项目架构与工程拆分2.1 前后端分离的整体请求链路这套项目本质上是一套“Vue 单页应用 Flask 接口服务 MySQL 数据库”的三层结构。请求链路大致是这样的浏览器加载 Vue 页面后用户在页面上操作Axios 发出 HTTP 请求请求打到 Flask 定义的路由上视图函数从数据库里取数据再以 JSON 格式返回给前端前端拿到数据后更新界面。开发模式下Vue 跑在一个端口Flask 跑在另一个端口两者之间需要做跨域转发。我习惯让 Vue 的 devServer 把/api开头的请求自动转发到本地 Flask 服务这样前端代码里只需要固定写/api前缀不用关心后端到底部署在哪台机器。生产环境则可以用 Nginx 托管前端打包后的静态文件再把/api请求转发到 Flask 进程。这个链路搞清楚了前端的调试和后端的部署就都不会乱。后端的模块划分也按这条链路切认证模块负责注册登录职位模块负责发布和查询申请模块负责投递和处理管理模块负责后台审核。这样每个文件都有明确职责后面扩展功能也不用把代码全塞进一个文件里。2.2 角色权限模型与路由粒度系统里至少有三种角色学生、雇主、管理员。数据库里我建议直接用role字段区分角色而不是给三种角色各建一张用户表。前者在登录验证、外键关联、查询统计上都更简单后者除了让代码显得“很规范”之外实际只会增加联表复杂度。权限控制必须双层做。后端管数据安全前端管页面展示。后端一般用装饰器加 JWT 身份识别来实现比如创建职位接口只允许雇主调用审核接口只允许管理员调用普通学生请求直接返回无权限。前端则通过路由的 meta 配置判断页面是否需要登录以及限制某些页面只允许指定角色进入。我踩过一个很典型的坑一开始只在页面层做了权限判断后端接口完全裸奔。结果用普通学生账号登录后手动构造一个请求往接口发竟然能访问到雇主面板的数据。从那以后我就记住了前端的权限控制只是个体验优化后端校验才是真正的安全底线。3. 数据库设计三张核心表与业务字段3.1 用户表、职位表、申请表的关键字段设计数据库设计是这个项目最重要的基础工作。真正撑起业务的可以用三张主表概括用户表、职位表、申请表。把这三张表想透后面写接口就像填空题一样轻松。用户表的核心字段包括id、username、password_hash、role、phone、avatar、create_time。密码字段绝对不能存明文要存哈希值这一步直接决定系统是否安全。职位表的核心字段包括id、employer_id、title、category、description、salary、salary_unit、headcount、location、status、deadline、create_time。其中employer_id关联用户表表示这个岗位是谁发布的salary_unit用来区分时薪、日薪还是月薪避免薪资单位混乱。申请表的核心字段包括id、job_id、student_id、resume_text、audit_status、apply_time、update_time。job_id和student_id分别关联职位表和用户表resume_text存放学生申请时填写的介绍或留言。字段命名统一用英文小写加下划线方便后面写 SQL 和 ORM 查询。表名核心字段职责userid, username, password_hash, role, phone, avatar三类账号统一存放jobid, employer_id, title, description, salary, status兼职岗位基础信息job_applicationid, job_id, student_id, audit_status, apply_time学生申请与处理进度3.2 状态字段设计与结算可行性很多同学在设计表结构时最常忽略的就是状态字段。职位表里的status应该设计成字符串枚举待审核、招聘中、已结束。管理员在后台审核时只需要修改这一个字段前端列表也能直接按状态筛选不用做复杂的条件拼接。申请表的状态可以更细一点pending待处理、accepted已录用、rejected未通过、working进行中、completed已完成、cancelled已取消。这个状态机看起来啰嗦但实际非常有用因为“结算”环节依赖它。只有状态为completed的申请才能触发工资结算标记防止雇主造出“人没干完却说已经结算”的乱账。如果后续要做真实薪酬管理可以在申请表基础上增加一张结算表记录job_id、student_id、amount、pay_status。课程设计阶段一般不需要对接真实支付但表结构可以先建好演示时用“标记结算”来模拟即可。数据表设计得清爽后面做统计报表时才拿得出来干净数据。4. Flask 后端从骨架到核心接口4.1 虚拟环境、依赖安装与应用工厂后端落地的第一步是先把环境和工程骨架搭好。在 PyCharm 底部的 Terminal 里执行mkdir campus-work cd campus-work python -m venv venv source venv/bin/activate # Windows 上为 venv\Scripts\activate pip install flask flask-cors flask-sqlalchemy flask-jwt-extended pymysql每个人都会写这几条命令但我要强调一个点虚拟环境务必先激活再装依赖。见过太多人装了一堆包结果全部装进全局环境项目换台电脑跑起来就是各种 Missing module 报错。工程代码的组织方式建议把数据库实例和 JWT 实例单独抽到一个文件里避免循环导入。下面是一个最小可运行的应用工厂写法# app/__init__.py from flask import Flask from flask_cors import CORS from flask_sqlalchemy import SQLAlchemy from flask_jwt_extended import JWTManager db SQLAlchemy() jwt JWTManager() def create_app(): app Flask(__name__) app.config.from_object(config.DevConfig) db.init_app(app) jwt.init_app(app) CORS(app, resources{r/api/*: {origins: *}}) from app.views.auth import auth_bp from app.views.job import job_bp from app.views.application import application_bp app.register_blueprint(auth_bp) app.register_blueprint(job_bp) app.register_blueprint(application_bp) return app应用工厂的好处是当你以后要加测试环境、加新的蓝图模块时只需要在create_app里增加配置和注册代码不需要改动启动入口。4.2 登录注册接口与 JWT 鉴权注册接口负责把客户端传过来的用户名、密码、手机号等信息写入用户表。密码一定不能用明文使用werkzeug.security自带的工具做哈希from werkzeug.security import generate_password_hash, check_password_hash auth_bp.route(/api/auth/register, methods[POST]) def register(): data request.get_json(forceTrue) if not data or not data.get(username) or not data.get(password): return jsonify(code1, msg参数不完整) user User.query.filter_by(usernamedata[username]).first() if user: return jsonify(code1, msg用户名已存在) new_user User( usernamedata[username], password_hashgenerate_password_hash(data[password]), roledata.get(role, student) ) db.session.add(new_user) db.session.commit() return jsonify(code0, msg注册成功)登录接口的逻辑是“查用户 验证密码 签发 token”。token 统一用 Flask-JWT-Extended 生成登录成功后返回给前端保存后续请求带上这个 token后端就能识别当前登录的是谁。写接口时有一个经常被忽略的细节identity到底存字符串还是整数前后一定要保持一致。如果签发 token 时写的是str(user.id)那后面接口里取到的就是字符串类型做数据库查询时如果不做类型转换轻则查不到数据重则直接报错。我自己就在这个细节上排查过半小时。4.3 兼职发布与申请接口的实现思路职位发布接口只允许雇主角色访问。实现上除了常规的插入逻辑要记得两个关键点第一职位发布时status默认是“待审核”不能直接变成“招聘中”第二employer_id必须从当前登录用户的身份里取不能信任前端传来的任何参数。前端传参数这件事我遇到过直接把别人的用户 ID 塞过来冒充发布者的所以后端必须自己解析 token 拿身份。申请接口对应学生的动作。学生在职位详情页点击“申请”时后端需要检查三件事职位是否存在、职位是否还在招聘中、学生是否已经申请过。前两个检查比较直接第三个“重复申请检查”是最容易被漏掉的如果不做同一个学生可以一天之内把同一个岗位申请二十次生成一堆脏数据。最稳妥的做法是在数据表结构层面直接加唯一约束class JobApplication(db.Model): __tablename__ job_application id db.Column(db.Integer, primary_keyTrue) job_id db.Column(db.Integer, db.ForeignKey(job.id), nullableFalse) student_id db.Column(db.Integer, db.ForeignKey(user.id), nullableFalse) audit_status db.Column(db.String(16), defaultpending) __table_args__ (db.UniqueConstraint(job_id, student_id, nameuniq_job_student),)这样即使接口里的判断漏了数据库也会兜底不会允许重复插入相同的组合。5. Vue 前端实现与联调5.1 Vue 工程初始化与页面路由规划前端工程建议放在项目的独立子目录里用vue create frontend创建选择 Vue Router 模式。页面的划分尽量按角色来切模块这样代码结构和后端的蓝图划分是对应的公共页面首页、职位列表、职位详情、登录页、注册页。学生页面个人中心、我的申请列表、申请详情。雇主页面发布兼职、我发布的职位、收到的申请处理。管理页面职位审核列表、用户管理、基础统计。路由规划时把需要登录的页面统一加上meta: { requiresAuth: true }需要雇主身份的页面再加meta: { role: employer }。这个做法比在每个组件里手动判断登录状态要干净得多也方便全局路由守卫统一拦截。5.2 axios 请求封装、token 存储与页面守卫前端请求封装是每前后端分离项目都绕不开的环节。我习惯先封装一个统一的 request 模块避免每个页面重复写 baseURL 和 headers// src/utils/request.js import axios from axios const request axios.create({ baseURL: /api, timeout: 10000 }) request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) config.headers.Authorization Bearer token return config })token 存储在 localStorage 里页面刷新后还能继续读取。路由守卫放在全局配置里router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) } else { next() } })路由守卫生效后前端就不会再出现“没登录也能看到个人中心”这种体验问题。如果对角色有要求还能在守卫里进一步判断当前用户角色是否包含在to.meta.role中不匹配就跳回首页。5.3 联调时的跨域转发配置开发阶段 Vue 默认跑在 8080 端口Flask 跑在 5000 端口端口不同必然产生跨域问题。最省事的方案不是在后端配一堆允许跨域的代码而是在 Vue 的配置里设置跨域转发// vue.config.js module.exports { devServer: { port: 8080, proxy: { /api: { target: http://127.0.0.1:5000, changeOrigin: true } } } }配置之后前端代码里请求/api/jobs浏览器里看到的是访问 8080 端口实际上 devServer 会把请求转发给 5000 端口的 Flask。这样比在 Flask 里直接做跨域放开更接近真实生产链路上线时只需要把转发地址改成正式服务器地址前端代码一行都不用动。注意 Vue CLI 默认项目没有这个文件需要手动创建改完之后要重启npm run serve才能生效。我第一次改这个配置时忘了重启怎么刷新都还是报跨域折腾半天才发现是配置没生效。6. PyCharm 在开发周期中的高效用法6.1 解释器配置与依赖管理很多人用 PyCharm 只把它当成一个高级编辑器这有些浪费。新建项目时建议直接在 Settings 的 Project 解释器里选择创建虚拟环境PyCharm 会自动生成 venv 目录并在终端里默认激活虚拟环境。这样你每次打开终端提示符前面都会显示当前用的是哪个环境不会出现“明明装了依赖却 import 报错”的问题。代码里 import 飘红时不用手动开命令行跑 pip直接在解释器面板里点加号搜索安装。我常看到新手手动在全局环境里装了一堆包项目环境里什么都没有结果接口一跑就模块找不到。用解释器面板管理依赖可以保证所有安装都落在当前项目虚拟环境里。6.2 断点调试与数据库面板Flask 接口排查问题的时候我强烈推荐用断点调试而不是到处写 print。在视图函数那一行左边单击加一个断点启动调试模式请求一进来就会停在断点位置此时你能清清楚楚看到request.args、请求体data、当前登录用户user这些变量的真实值。问题出在哪一步基本一眼就能看出来。PyCharm 自带的 Database 面板也可以直接连接 MySQL双击表就能看到数据比来回切换到外部数据库软件省事很多。当接口返回了意料之外的数据先看数据库面板里存的值对不对能快速判断问题出在后端逻辑还是前端渲染。调试 Flask 类项目这两样配合得好开发效率能提升一半以上。7. 踩坑清单与常见问题速查7.1 跨域、端口占用、中文乱码等高频故障这个项目我在带人做的过程中出现频率最高的错误就那么几类整理成表格放到这里方便直接对照排查。现象可能原因处理建议请求接口报 Access-Control-Allow-Origin 错误前端未配置转发或 Flask 未启用 CORS开发阶段启用 vue.config.js 转发后端配合 CORS 配置允许来源Flask 启动时报 Port 5000 already in use端口被占用换端口启动app.run(debugTrue, port5001)中文数据在数据库里变成??数据库字符集不是 utf8mb4建库时指定DEFAULT CHARSETutf8mb4连接串也带上 charsetFlask 接收 JSON 返回 415前端未设置 Content-Typeaxios 传对象默认 json手写 fetch 时需要自己设置请求头登录后页面刷新就退出token 只放在 js 变量里写入 localStorage路由守卫从 localStorage 读取同一学生重复申请同一职位缺少唯一约束数据表加 unique 约束接口再加一次业务判断7.2 这类项目常见的开发节奏误区太多人一上来就写代码结果跑着跑着把自己绕进去。我总结的合理顺序是先画角色用例图再设计数据表和状态机然后写 Flask 接口最后再做 Vue 页面。如果顺序反了大概率会因为前端页面的展示需求反复调整后端接口的返回结构最后把两边都改得很脏。另一个常见误区是数据表设计得过分简单恨不得所有信息都塞进一张“万能表”。等到做结算统计或者后台报表时才发现拿不出干净数据。那些看似不起眼的字段比如申请时间、更新时间、状态值、金额单位建表的时候就要一次性设计好。7.3 简单部署与交付建议如果只是课程设计或者毕业设计答辩不需要一上来就搞复杂的云上架构。一个很标准的展示环境是这样前端执行npm run build生成 dist 静态目录Flask 用 Gunicorn 方式启动再用 Nginx 同时托管前端静态文件和/api请求的转发。这里特别提醒一点上线部署时不要用 Flask 自带的调试服务器它处理并发能力很弱正常只用于开发环境。把debugTrue关掉用正式的服务方式启动性能和安全性都会好很多。答辩演示时也建议提前把服务跑起来不要现场开调试模式否则浏览器一开就有报错弹窗观感很差。这套系统完整做下来我个人最真实的体会是框架本身并不值钱值钱的是你有能力把一条业务链路完整盘顺。做校园兼职系统最舒服的时刻不是某个接口终于跑通而是看到“学生发布申请、雇主审核、管理员把关”这条流程在你设计的数据库状态下稳定流转。最后给正在做类似题目的朋友一个建议先花一个晚上把表和状态机画清楚再去碰 Flask 和 Vue 的代码。我是踩过两次推倒重来的坑之后才彻底信服这个顺序的。
阅读完成 · 觉得有帮助?
咨询建站