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

校园礼服租赁系统全栈开发:Django+Flask+Vue项目复盘

校园礼服租赁系统全栈开发:Django+Flask+Vue项目复盘 ★ FEATURED ARTICLE
校园礼服租赁这需求在大学里其实特别真实毕业典礼要穿学士服、答辩要正装、晚会要晚礼服、社团演出要演出服买一套动辄几百上千穿一次就压箱底学生之间互相租借又缺少信任和管理。我之前在PyCharm里用Python把这么一套系统完整做出来了后端用Django做核心业务、Flask做轻量接口前端配Vue做界面前后端分离开发本文就把整个项目的技术选型、数据库设计、前后端联调、环境配置和排坑过程完整复盘一遍。适合正在做毕业设计、课设或者想练手全栈Python项目的同学参考也适合刚接触DjangoVue组合、想知道这套技术栈怎么配合干活的人。我先把结论放在前面这套系统能否顺利跑起来决定因素不在代码量而在三个环节——一是数据模型设计得够不够稳二是前后端接口约定是否清晰三是PyCharm开发环境里的虚拟环境和调试配置是否顺手。后面我按实际开发顺序一层层拆开讲。1. 需求场景与技术选型复盘1.1 校园礼服租赁场景到底要解决什么问题做项目之前我习惯先把真实场景里的痛点列出来再反推技术需求。校园礼服租赁表面上是“礼服信息展示下单”实际上核心矛盾有三点第一礼服属于非标品尺码、颜色、场合、新旧程度都会影响可租性普通商品模型套不进去第二租赁有明确的时间边界同一件礼服在同一时间段不能租给两个人这就有库存与订单的冲突判断第三租赁过程必然涉及押金、租金、损坏赔偿金额状态必须可追溯。对应到技术实现上就要求系统必须有一个可靠的订单状态机、一套按时间段查询可租库存的逻辑以及至少三类角色学生、管理员、游客。这些需求决定了后端不能只是一个简单的CRUD而是需要有清晰业务层设计的工程。我选择Django做主后端就是看中它自带的ORM、Admin后台和迁移机制能快速兜住这些业务规则。1.2 为什么采用DjangoFlask双后端方案很多同学看到“DjangoFlask”会觉得奇怪两个Web框架为什么同时用其实这是我在开发中摸索出的分工方案不是炫技。Django的强项是全套解决方案自带的ORM映射、Admin管理后台、表单校验、迁移工具非常成熟特别适合做核心业务系统——用户、礼服、订单、评价这些模块用Django管理最省心调试起来也稳。但Django也有笨重的一面写轻量的统计接口、处理文件上传回调、给前端提供一些临时性的聚合数据起一个完整Django ViewSet显得杀鸡用牛刀。这时候Flask的轻量优势就体现出来了几个Blueprint加装饰器就能快速出一个接口。我在项目里把租金计算服务、礼服热度统计、消息通知这三个相对独立的模块用Flask搭Django通过HTTP调用Flask暴露的内部接口两个服务在PyCharm里同时启动互不干扰各干各擅长的活。这种双后端架构在前后端分离场景下还有一个额外好处角色和职责清晰了——Django只负责业务数据和鉴权Flask只负责逻辑计算和聚合查询哪个环节出问题一眼就能定位到具体服务排错路径比单体应用短很多。1.3 Vue在项目里的角色与优势前端我选了Vue原因很直接它对Python后端开发者最友好模板语法和组件化思维容易上手生态里vue-router、Pinia、Element Plus这些配套齐全踩坑资料多。Vue负责SPA单页应用通过axios向后端API拿数据页面切换不刷新体验比服务端模板渲染好一个档次。在这个项目里Vue承担的三个核心责任是礼服列表的筛选与分页展示、租赁流程的订单表单与状态流转、个人中心的数据面板。尤其列表筛选这块Vue的计算属性和组件插槽非常实用——我封装了一个礼服卡片组件正常情况只显示详情在管理员模式下通过插槽注入“下架”“编辑”按钮同一套组件两处复用代码量省了三成。组件插槽这套机制把这个项目的复用性拉满是纯后端思维转前端时最值得先学会的技能点。2. 系统核心模块与数据库建模2.1 角色与权限设计学生、管理员怎么划分权限设计我采用的思路是“模型级别的状态字段视图级别的登录校验”没有引入太重的权限框架。User模型通过is_staff字段区分管理员和学生管理员可以进入Django自带的Admin后台直接管理礼服数据学生在Web前端只能看到自己的订单和个人信息。游客可以浏览礼服列表和详情但提交订单前必须登录。这样划分的考虑是校园租赁系统规模有限用户行为差异不算复杂不必为每个接口单独挂权限类。真正要重点保护的是押金和订单状态这些资金敏感数据所以Order和Payment相关的视图我会额外加一层登录校验和对象归属校验确保学生只能查自己的订单管理员才能改订单状态。在这个基础上Django Admin后台还可以配置ModelAdmin里的list_display、list_filter让管理员的日常维护工作不用写一行前端代码。2.2 礼服、订单、评价三大核心数据表设计数据库我设计了五张核心表User、Dress、Order、OrderItem、Comment。Dress表存放礼服基本信息包括名称、分类、颜色、尺码、图片URL、日租金、押金、所在校区、库存数量和状态。这里有个容易忽略的点礼服分类建议用单独的choices常量而不是建分类表因为服装分类基本固定常量化之后查询和筛选都简单。Order表是整套系统的重心字段包含订单号、用户外键、总租金、押金、订单状态、租借开始日期、归还日期、创建时间。OrderItem表处理“一个订单租多件礼服”的场景每条记录关联礼服外键、单价和租期天数。把订单和礼服拆成两张表好处是以后要做款式统计、营收报表都方便不用去解析订单里拼出来的长字符串。Comment表负责评价体系关联用户和礼服存评分和评论内容。我在设计时给它加了一个order外键保证“下单过才能评论”从源头拦截恶意刷评。这四张表之间都是标准外键关系Django的ORM在迁移时会自动创建索引和约束实际查询性能在校园规模下完全够用。有一点必须提醒图片字段千万别直接存文件路径字符串我一开始为了省事直接存相对路径结果前端部署到不同域名下图片全部裂开。正确做法是存一个可访问的绝对路径或者URL前缀拼接字段方便前端直接用。2.3 订单状态机与租期计算的细节设计订单状态是租赁系统的灵魂我设计了六个状态待付款、已付款待发货、租赁中、已归还、已取消、已完成。学生从提交订单到归还礼服状态只能按固定方向流转管理员后台操作也只是推动状态前进不能随意跳转。这个状态机用Django model里的IntegerField加choices实现每个状态转换在View层做校验防止前端的恶意请求直接篡改状态。租期计算上我用了时间差加一的方法租借开始日期到归还日期的天数加1为什么加1因为第一天也算一个租赁日。比如6月1日借、6月3日还实际占用是3天如果直接相减只得到2天租金就会少算。这个细节在刚开始测试时没注意导致测试订单租金一直比手算少一天排查了半天才发现是边界条件的问题。库存冲突判断的逻辑也可以展开说一下查询某件礼服在某日期段是否可租不能只看“礼服是否在库”而是要把已有的时间区间拉出来做重叠判断。我写了一个函数遍历该礼服的已生效订单如果新租期与任何一个已存在订单的租期有重叠就判定不可租。这个函数放的位置要尽量靠近数据层避免在多个视图里重复实现产生不一致。3. 后端实战Django管线与Flask接口实现3.1 搭建Django工程与app拆分实践创建Django项目我用的是标准动作先建虚拟环境然后用pip装Django再通过django-admin startproject和python manage.py startapp拆分模块。这里给新手的建议是一个业务域一个app不要把所有模型塞进一个app里。我拆成了users、dresses、orders、comments四个app每个app的models.py、views.py、urls.py各自独立后续维护比单个大app清爽得多。创建app这个命令本身很简单但很多新手卡在“app建好了为什么页面访问不到”这一步。原因往往是没有在项目的settings.py里的INSTALLED_APPS注册这个appDjango默认不会自动扫描你新建的目录。建完app之后一定要记得在settings.py的INSTALLED_APPS列表里加上一行然后才能做makemigrations和migrate。模板和静态文件的组织也有讲究。前后端分离之后Django的templates目录基本可以空着真正的前端页面全部由Vue构建后生成Django只负责提供API数据。但为了本地调试方便我会在Django里配一个简单的健康检查视图返回JSON状态确认后端服务活着。3.2 ORM查询、对象删除与事务处理的细节Django的ORM是我用下来最顺手的一层但细节坑不少。执行查询时我习惯用filter()链式调用而不是get()因为get()找不到对象直接抛DoesNotExist异常处理起来麻烦而filter()返回的QuerySet即使为空也不报错配合.exists()判断存在性非常丝滑。对象删除这块要格外小心。Django的.delete()方法默认级联删除也就是外键关联的子记录会被一起删掉。这在“清理测试数据”时很爽但在生产场景就可能误伤——比如你删了一件礼服所有关联的订单记录、评论记录全部没了用户历史订单页面就会缺数据。我的处理方案是把delete语义改成“软删除”在Dress表加一个is_active字段下架礼服只是把is_active设为False查询默认不过滤掉已下架但订单数据和评价数据完整保留。只有在后台“彻底删除测试数据”时才调用真正的delete()。订单金额计算和库存扣减涉及多次读写必须用事务包裹。Django里用transaction.atomic()装饰器或with块包住业务逻辑比如创建订单时要先判断库存、再生成订单记录、再更新礼服状态这中间任何一步失败前面写的记录要全部回滚否则会出现“订单没生成但库存扣了”这种脏数据。我踩过一次这个坑后来所有写操作都强制套事务。3.3 Flask轻量API模块与FastAPI对比选型在把这套系统项目分享给朋友时经常被问到“为什么不用FastAPI”。我说下个人感受FastAPI的优势是异步性能和自动生成OpenAPI文档但对于校园租赁这种业务IO密集、数据量不大的场景异步带来的性能提升感知不强。Flask生态成熟、资料多、和Django同属WSGI体系学习成本更低我可以把精力放在业务逻辑而不是框架特性的学习上。Flask在这个项目里主要负责三件事租金试算接口、礼服热门排行统计、站内消息通知。每个模块一个Blueprint内部再分路由代码结构保持和Django的app风格统一。Flask的启动入口我单独建了run.py配置好跨域CORS注册蓝图然后监听一个独立端口。这样PyCharm里可以同时启动Django8080和Flask5001各司其职。要注意Flask和Django共存时的一个小坑两个服务的数据模型不能共享同一个数据库连接配置。我是让Flask独立使用SQLAlchemy直连同一套MySQL库表结构和Django的迁移保持一致。这样做的好处是改字段时只需要在Django侧改模型、做迁移Flask侧只要查询现有表结构就行避免双份迁移文件互相打架。3.4 接口规范与登录鉴权流程前后端联调最怕的是接口约定不清。我统一采用RESTful风格资源用复数名词比如/api/dresses/、/api/orders/创建用POST、更新用PUT/PATCH、删除用DELETE。响应格式也做了统一封装成功时返回data字段失败时返回code和message字段前端axios拦截器统一处理避免每个页面都写try-catch。登录鉴权我用的是JWT方案。用户在前端输入账号密码Django侧调用登录接口校验成功后返回一个有效期为7天的token前端存在localStorage里每次请求通过Authorization请求头带上。Django后端用一个装饰器解析token、校验有效性再通过request.user注入当前用户。这个方案比Session更契合前后端分离的场景也方便以后做小程序端复用同一套鉴权逻辑。有个细节要提醒跨域配置一定不能漏。前端Vue跑在localhost:5173Django跑在localhost:8080浏览器会拦截跨域请求必须在Django的CORS配置里把前端地址加入白名单Flask侧也一样配。否则你会在浏览器控制台看到一堆红色报错以为是后端挂了其实是CORS没通。4. 前端Vue工程化与前后端联调实录4.1 Vue环境搭建与项目初始化细节前端我用Vite搭建Vue3项目Node环境先装好然后执行npm create vuelatest命令初始化。这个脚手架会问你需不需要Router、Pinia、ESLint之类的功能按需勾选就行。项目生成后第一件事是npm install装依赖这一步慢而且容易失败国内环境建议把npm registry切到国内镜像源用npm config set registry命令即可。依赖安装过程中有几个经典报错比如版本冲突和node-gyp编译失败大多是Node版本和依赖版本不匹配导致。我给的建议是锁定Node版本项目根目录放一个.nvmrc文件指定Node 18或20团队协作时大家统一版本能省掉很多无意义的排错时间。前端目录结构我按功能模块化views目录放页面组件components目录放通用组件router目录配路由表stores目录放Pinia状态api目录统一封装后端接口请求。页面之间跳转用vue-router声明式导航涉及订单提交成功跳转这种场景用编程式导航并携带参数。4.2 路由配置、状态管理与请求封装路由表我分成两类公共路由和需要登录才能访问的路由。公共路由包含首页、礼服列表、礼服详情、注册登录。个人中心、订单管理、管理后台这些页面通过路由守卫拦截未登录跳转到登录页并带上redirect参数登录成功后再跳回原来的页面体验很顺滑。状态管理我用了Pinia主要存两类数据用户登录信息和订单草稿。用户信息在登录成功后写入store同时持久化到localStorage刷新页面不丢失。订单草稿用于“礼服详情页点击租借→填写租期→确认订单”的多步骤流程每一步操作先写store最后提交时一次性传给后端避免频繁请求接口。axios封装是前后端联调的枢纽。我建了一个request.js统一设置baseURL、超时时间、请求拦截器加token、响应拦截器处理错误码。后端返回401时拦截器自动清除本地token并跳转登录页返回500时统一弹错误提示。这样业务代码里只需要关心成功后的数据处理错误处理全部收敛到一个文件里。4.3 跨域配置与多环境部署细节开发环境的跨域问题我在前面提到过了生产环境也要提前规划。前端构建时执行npm run build产物是一堆静态资源我把它放在Nginx的html目录下Nginx里配置反向代理/api前缀的请求转发到Django服务/flask前缀转发到Flask服务前端路由用try_files配置实现history模式刷新不404。这套配置意味着前端代码里不要硬编码后端地址而是统一用相对路径/api开头由Nginx在做分发。我一开始图省事前端封装的baseURL写成了http://localhost:8080结果部署到服务器上所有请求跨域、配了半天Nginx也不对后来改成相对路径加转发才解决。前后端分离项目的部署域名和路径规划一定要提前做别等代码写完了再补。多环境配置也值得用一套规范管理本地开发、测试环境、生产环境分别对应不同的.env文件里面定义API地址等变量。Vite在构建时会自动读取对应的环境变量文件我只需要在请求封装里读一下环境变量即可这样换环境部署不用改代码。5. PyCharm开发环境配置与调试经验5.1 虚拟环境与解释器配置PyCharm对Python项目的支持是我选它的核心理由。项目创建第一步就是配置虚拟环境推荐用venv而不是直接选全局解释器。我在PyCharm的Settings里找到Python Interpreter选择New Environment基于系统Python创建虚拟环境之后项目依赖全部装在venv里不会污染全局包列表。虚拟环境创建好后在PyCharm的Terminal面板里会自动激活命令行直接执行pip install就能装包。这里有个PyCharm的使用技巧要装的第三方库可以直接在设置界面搜索安装比如Django、Flask、djangorestframework、django-cors-headers这些在包的列表里勾选安装就行不用记住每个包名。但更复杂的包比如某些需要编译的依然建议用命令行pip装因为能看到完整安装日志。导入已存在的Django项目时有同学总找不到正确的打开方式。正确做法是直接用PyCharm的Open按钮选择项目根目录PyCharm会自动识别manage.py并配置好Django支持。如果识别失败手动在Settings的Languages Frameworks里设置Django项目根目录和settings.py路径即可。5.2 数据库连接与可视化配置PyCharm专业版自带数据库面板我直接用它连MySQL写SQL调试数据比反复看ORM日志高效得多。面板里配置好数据库连接后可以浏览表结构、执行自定义SQL、甚至直接修改字段值调试订单状态流转时非常直观。社区版没有这个功能我的建议是本地装一个DBeaver或者DataGrip效果同样好。数据库连接字符串在Django里写在settings.py的DATABASES配置我这里用的是MySQL驱动用的PyMySQL需要在项目入口文件里主动调用pymysql.install_as_MySQLdb()让Django识别。这一步容易漏漏了会报“No module named MySQLdb”错误属于新手必踩的坑。设计表结构时有一个小习惯帮我省了很多事把权限共性字段抽到一个抽象基类模型里比如created_at、updated_at、is_active这些字段子模型继承即可这样不用在每张表里重复写迁移时Django会自动把基类字段带过去。5.3 断点调试、热重载与版本管理PyCharm的断点调试是我排逻辑错误的杀手锏。我一般在视图层和service层的关键代码行打上断点启动Debug模式逐步查看变量的值变化。比如查订单冲突判断函数时断点能看到每个时间段的比较结果跟手算一对照就知道逻辑错在哪。Django自带Auto-Reload特性改完代码保存后服务会自动重启不用手动重启这个对开发效率提升很大。Flask默认不带热重载需要在启动时设置debugTrue或者用--reload参数。我在run.py里直接设置了app.run(debugTrue, port5001)改Flask代码保存即生效。版本管理这块PyCharm集成了Git工具我习惯在每次做一个完整功能后提交一次比如“完成礼服列表筛选”“完成订单提交接口”这样粒度的commit。遇到改坏代码的情况直接git checkout回退比手动撤销快得多。项目里我还加了.gitignore文件把venv、node_modules、pycache、.env这类不该进版本库的东西全部过滤掉避免同事clone下来一堆垃圾文件。6. 高频问题排查与避坑速查表6.1 前端依赖与tsconfig报错的倒腾记录Vue3 TypeScript项目在创建或运行时常遇到的“failed to load tsconfig vue/tsconfig/tsconfig.web.json: tsconfig not found”报错表面上是找不到配置文件实际上大部分时候是依赖没装全或者版本不一致。我碰到这个问题的处理顺序是先执行npm install确认所有依赖已安装然后检查node_modules里有没有vue/tsconfig这个包如果还没有单独执行npm install -D vue/tsconfig最后把tsconfig文件里的extends引用路径改为相对路径。Vue项目装在别人电脑上跑不起来的现象也很常见根因基本都是package-lock.json没有被同步提交。这个锁文件锁定了每个依赖的精确版本别人clone代码后执行npm ci就能恢复出一模一样的依赖树。所以把package-lock.json提交进Git非常重要千万别手滑把它加进.gitignore。6.2 Django迁移冲突与外键约束问题多人协作改模型时经常遇到makemigrations生成冲突迁移文件的情况。我的习惯是每次合并代码后第一时间执行makemigrations和migrate如果有冲突迁移在迁移文件目录里按时间顺序理清依赖关系删掉多余的迁移文件再重新生成。当然这只是我的做法更稳妥的做法是用Django的迁移合并机制让Django自动处理依赖。但小项目手动理一遍其实更直观还能顺便看看迁移产生的SQL。外键约束相关的报错通常发生在删除有子关联的数据时。比如删一个关联了订单的用户MySQL会报外键约束错误。这个问题的正确解决思路是先用ORM查清楚子关联数据该处理的处理再删父数据。我在视图层写了一个安全删除的工具函数先列出外键关联表再做操作会比直接在迁移层设置级联删除更可控。6.3 图片上传、回显与静态文件路径礼服图片上传涉及两个环节上传接口和显示接口。我上传用的Django FileField加自定义上传路径保存后拿到文件的URL存入数据库。这个方案要注意的是MEDIA_ROOT和MEDIA_URL的配置Django里要在settings.py设置好并在项目的urls.py里用static()函数给媒体文件提供访问路由。开发环境下能正常显示生产环境记得让Nginx直接托管媒体目录。图片回显失败是最常见的问题报错通常是“图片路径404”或者“图片损坏”。我总结了两条排查路径一是确认数据库存的路径确实可访问二是确认MEDIA_URL和Nginx的映射一致。一个小技巧是图片字段允许为空时要给前端一个默认占位图URL否则前端拿到空值会渲染出一张破图图标体验很掉价。6.4 Flask接口性能与部署配置Flask接口在本地调试时响应很快但部署到服务器后偶尔出现首请求慢、不稳定等情况。我自己排查过一种情况是可以优先怀疑的数据库连接没有用连接池导致每个请求都重新建立数据库连接。给Flask的SQLAlchemy配置一个连接池后整体响应快了不少。配置连接池的方式也比较简单在引擎字符串里加上pool_size和pool_recycle等参数即可。Flask部署我还踩过一个坑直接使用Flask内置服务器对外提供服务这在生产环境下并发一高就崩。正确做法是用Gunicorn或uWSGI作为WSGI服务器启动Flask应用Nginx做前置反向代理。本地开发用内置服务器没问题但部署文档里一定要写清楚生产启动命令不要像我第一次部署时一样图省事拿app.run()顶上去结果扛不住并发连接。写在最后的一点个人体会这套校园礼服租赁系统从头到尾做完我最大的感受是技术选型永远服务于业务场景。Django负责稳、Flask负责轻、Vue负责体验PyCharm负责效率每一层都干自己最擅长的事组合起来开发进度反而比堆新技术框架更干净、更顺手。想起最初没有统一响应格式那段日子前端同事对接接口时一会儿解析这个字段、一会儿解析那个字段被搞得焦头烂额后来把接口规范定下来以后前后端联调时间直接砍掉了一半。有时候问题不在代码写得少而在约定不清楚、边界没想明白这种隐藏时间成本远比技术难点本身更磨人。希望这篇复盘能帮正在做类似Python全栈项目的同学少走几段弯路哪怕只避开其中一两个坑也值了。
阅读完成 · 觉得有帮助?
咨询建站