一、项目背景与痛点
高校校园内学生闲置物品流转需求旺盛,课本教辅、电动车、电子产品、生活用品、运动器材等闲置物品堆积严重,线下摆摊交易耗时费力,通用二手平台又无法适配校园专属场景,现有交易渠道存在诸多痛点:
- 通用二手平台鱼龙混杂,校外人员混杂不安全:闲鱼、转转等公共平台人员复杂,无法限制校外人员进入校园交易,线下面交存在人身与财产安全隐患;
- 无校园专属身份校验,虚假信息泛滥:普通二手平台无需实名认证,学生容易遇到虚假商品、恶意砍价、放鸽子等不良交易行为;
- 缺少校园就近交易功能,无法筛选同城同校卖家:无法精准匹配本校卖家,远距离交易失去校园二手面交便捷性;
- 缺少专属沟通与交易闭环:商品留言咨询、订单创建、交易完成、售后评价流程割裂,无法一站式完成全流程交易;
- 无后台审核机制,违规商品无法管控:违规违禁商品、虚假标价商品随意发布,平台无法统一管控内容质量。
针对校园二手交易的专属场景痛点,本次基于 Python + Django 4.2 + MySQL + Redis 搭建轻量化校园二手闲置交易平台,仅限本校师生注册登录,对接校园学号完成实名认证,实现闲置商品分类发布、商品搜索与筛选、购物车收藏、在线留言问答、订单提交、线下面交确认、交易互评、管理员商品审核全套闭环功能,贴合校园近距离线下交易场景,补足专栏校园电商细分场景空白,和往期聊天室、网盘、爬虫、运维监控等所有项目无任何功能与代码重合。
二、核心目标与定位
本项目核心目标:搭建封闭化校园专属二手交易平台,实现师生学号实名认证 → 商品分类发布与后台审核 → 商品多条件筛选与搜索 → 商品详情留言咨询 → 闲置商品加入购物车/收藏 → 订单生成与交易状态流转 → 线下当面交易确认 → 买卖双方双向评价 → 违规商品下架管控完整校园二手交易闭环,打造仅限校内、安全靠谱、就近面交的轻量化二手交易系统。
项目精准定位:垂直校园场景的轻量化二手电商系统,采用 Django 原生 MVT 架构,无需前后端分离,降低部署与学习门槛;划分普通买家、卖家、平台管理员三种角色,权限完全隔离;主打无物流线上沟通、线下当面交割的交易模式,适配校园交易习惯,区别于传统需要快递发货的综合电商平台。
核心设计理念:校园封闭准入、身份真实可信、交易流程简洁、就近面交安全、内容严格审核、权限分级管控,完全贴合高校学生二手物品流转的真实使用需求。
三、整体技术方案
项目基于 Django 原生 MVT 分层架构开发,MySQL 存储用户、商品、订单、评价全量业务数据,Redis 缓存热门商品、首页轮播图、用户购物车数据提升访问速度,Django 自带后台完成商品与用户审核,整体分层架构流程图如下:
#mermaid-svg-p2FmtNSj5a1G6DvT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-p2FmtNSj5a1G6DvT .error-icon{fill:#552222;}#mermaid-svg-p2FmtNSj5a1G6DvT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-p2FmtNSj5a1G6DvT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-p2FmtNSj5a1G6DvT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-p2FmtNSj5a1G6DvT .marker.cross{stroke:#333333;}#mermaid-svg-p2FmtNSj5a1G6DvT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-p2FmtNSj5a1G6DvT p{margin:0;}#mermaid-svg-p2FmtNSj5a1G6DvT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT .cluster-label text{fill:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT .cluster-label span{color:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT .cluster-label span p{background-color:transparent;}#mermaid-svg-p2FmtNSj5a1G6DvT .label text,#mermaid-svg-p2FmtNSj5a1G6DvT span{fill:#333;color:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT .node rect,#mermaid-svg-p2FmtNSj5a1G6DvT .node circle,#mermaid-svg-p2FmtNSj5a1G6DvT .node ellipse,#mermaid-svg-p2FmtNSj5a1G6DvT .node polygon,#mermaid-svg-p2FmtNSj5a1G6DvT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-p2FmtNSj5a1G6DvT .rough-node .label text,#mermaid-svg-p2FmtNSj5a1G6DvT .node .label text,#mermaid-svg-p2FmtNSj5a1G6DvT .image-shape .label,#mermaid-svg-p2FmtNSj5a1G6DvT .icon-shape .label{text-anchor:middle;}#mermaid-svg-p2FmtNSj5a1G6DvT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-p2FmtNSj5a1G6DvT .rough-node .label,#mermaid-svg-p2FmtNSj5a1G6DvT .node .label,#mermaid-svg-p2FmtNSj5a1G6DvT .image-shape .label,#mermaid-svg-p2FmtNSj5a1G6DvT .icon-shape .label{text-align:center;}#mermaid-svg-p2FmtNSj5a1G6DvT .node.clickable{cursor:pointer;}#mermaid-svg-p2FmtNSj5a1G6DvT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-p2FmtNSj5a1G6DvT .arrowheadPath{fill:#333333;}#mermaid-svg-p2FmtNSj5a1G6DvT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-p2FmtNSj5a1G6DvT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-p2FmtNSj5a1G6DvT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p2FmtNSj5a1G6DvT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-p2FmtNSj5a1G6DvT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p2FmtNSj5a1G6DvT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-p2FmtNSj5a1G6DvT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-p2FmtNSj5a1G6DvT .cluster text{fill:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT .cluster span{color:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-p2FmtNSj5a1G6DvT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-p2FmtNSj5a1G6DvT rect.text{fill:none;stroke-width:0;}#mermaid-svg-p2FmtNSj5a1G6DvT .icon-shape,#mermaid-svg-p2FmtNSj5a1G6DvT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-p2FmtNSj5a1G6DvT .icon-shape p,#mermaid-svg-p2FmtNSj5a1G6DvT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-p2FmtNSj5a1G6DvT .icon-shape .label rect,#mermaid-svg-p2FmtNSj5a1G6DvT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-p2FmtNSj5a1G6DvT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-p2FmtNSj5a1G6DvT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-p2FmtNSj5a1G6DvT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 底层技术底座
后端框架:Python3.11 + Django4.2 原生MVT架构
数据库:MySQL8.0 存储全业务数据
缓存中间件:Redis 缓存购物车、热门商品
文件存储:Django原生Media存储商品图片
权限体系:自定义角色权限,区分三类身份
分页工具:Django原生分页器
安全防护:CSRF校验、恶意图片过滤、关键词拦截
用户前台交互层
注册登录/商品浏览/下单评价/留言咨询
路由视图分发层
分发页面请求与接口请求,参数校验
业务逻辑处理层
购物车/订单/商品发布核心业务逻辑
数据持久操作层
ORM操作MySQL完成数据增删改查
Redis缓存加速层
缓存热门商品、购物车、首页数据
管理员审核后台
审核上架商品、封禁违规用户、管理分类
交易状态流转层
待付款/待面交/已完成/已关闭订单状态切换
完整技术栈清单:
- Web 后端:Python 3.11、Django 4.2,原生 MVT 开发模式
- 数据库:MySQL 8.0,存储全部交易业务结构化数据
- 缓存服务:Redis,优化页面访问速度,持久化购物车数据
- 图片存储:Django Media 本地文件存储,适配商品图片上传
- 权限控制:自定义中间件校验用户身份,区分三类角色权限
- 辅助功能:Django 分页、表单校验、关键词过滤、CSRF 安全防护
- 后台管理:Django Admin 二次开发,适配校园平台专属审核后台
四、核心能力模块详解
1. 校园实名认证与权限管控模块
打造封闭校园交易生态,杜绝校外人员进入平台,从源头保障交易安全:
- 学号绑定注册:用户必须填写真实学号 + 姓名完成实名认证,管理员后台人工核验信息;
- 三层角色权限:普通买家仅可浏览、咨询、下单评价;卖家可发布、上下架自有商品;管理员拥有全站管理权限;
- 越权访问拦截:中间件拦截未登录、无权限用户的后台页面与发布商品接口;
- 账号状态管控:管理员可封禁恶意刷单、发布违规商品的用户账号。
2. 闲置商品发布与后台审核模块
标准化商品发布流程,平台前置审核,过滤违规虚假商品信息:
- 多级商品分类:划分教辅书籍、电子产品、代步工具、生活用品、运动器材五大核心分类;
- 完整商品信息录入:支持填写商品原价、售价、新旧程度、交易地点、商品详情、多图实拍上传;
- 先审核后上架:卖家发布商品后默认进入待审核状态,管理员审核通过才会展示在首页;
- 商品自主管理:卖家可随时下架、编辑、删除自家在售闲置商品。
3. 商品检索与筛选模块
适配学生快速找货需求,多维度精准筛选闲置商品,提升查找效率:
- 关键词模糊搜索:支持根据商品名称、详情文案全局搜索;
- 多条件组合筛选:支持按价格区间、商品新旧程度、交易地点、分类筛选;
- 排序功能:支持价格升序/降序、最新发布优先、热门浏览量优先三种排序方式;
- 首页热门推荐:Redis 缓存高浏览量商品,首页自动展示热门闲置好物。
4. 购物车与商品收藏模块
贴合电商常规交互,支持临时加购与长期收藏,方便用户对比挑选商品:
- 登录态购物车:绑定个人账号,换设备登录依旧保留购物车数据;
- 批量操作功能:支持购物车单件删除、批量删除、批量结算下单;
- 商品收藏夹:心仪商品可加入收藏,个人中心统一管理,快速回访;
- 库存联动校验:下单前自动校验商品是否已下架、是否已被他人抢先下单。
5. 商品留言咨询与订单交易模块
搭建买卖双方沟通桥梁,适配校园无物流、线下当面交割的专属交易流程:
- 商品页公开留言:买家可在商品页面提问,卖家后台实时回复,问答公开透明;
- 简易订单流程:创建订单 → 确认购买 → 线下约定地点面交 → 双方确认交易完成;
- 订单状态全程追踪:待确认、待面交、交易完成、交易关闭四种状态实时更新;
- 防重复下单机制:同一商品同一用户无法重复创建未完成订单,避免恶意占单。
6. 双向交易评价与平台管控模块
建立交易信用体系,约束买卖双方行为,规范校园二手交易风气:
- 买卖双向评价:交易完成后,买家可评价商品质量,卖家可评价买家交易履约情况;
- 信用分体系:恶意放鸽子、虚假描述商品会扣除对应信用分数,分数过低限制发布/下单权限;
- 违规内容过滤:自动拦截低俗、广告、违禁关键词,拦截违规评价与商品文案;
- 后台数据看板:管理员查看平台交易总量、商品发布数量、用户活跃度统计数据。
五、创新价值与亮点
- 校园封闭生态,交易安全性拉满:强制学号实名认证,仅限校内师生入驻,彻底规避校外陌生人员交易风险,适配校园线下面交场景;
- 极简无物流交易流程:摒弃传统电商快递物流环节,贴合校园面对面交易习惯,流程更简单、交易成本更低;
- 前置商品审核机制:所有商品人工审核后才可上架,从源头杜绝违规商品与虚假信息;
- 轻量化易部署,无需复杂前端工程:原生 Django MVT 开发,无需 Vue/React 前后端分离,零基础也可快速部署运行;
- 信用分约束交易双方:双向评价 + 信用分体系,有效解决校园二手交易放鸽子、货不对板等常见乱象。
六、应用前景与落地场景
- 单校专属二手交易平台:部署在校内服务器,服务全校师生,替代微信群、QQ 群零散二手信息;
- 高校课程设计/毕业设计优选项目:业务逻辑完整、贴合校园实际场景、代码通俗易懂,避开烂大街的通用商城系统;
- 社团闲置物资流转平台:学生会、社团内部器材、物资闲置流转,统一管理社团公共物品;
- Django 细分电商实战项目:区别于通用综合商城,聚焦垂直校园细分场景,简历项目差异化优势明显。
七、完整代码结构示例
1. 项目整体目录结构
django-campus-secondhand/
├── manage.py
├── market_project/ # 项目全局配置目录
│ ├── settings.py # 数据库、Redis缓存、媒体文件、中间件全局配置
│ ├── urls.py # 前台页面、后台管理、接口路由统一分发
│ └── middleware.py # 自定义权限校验中间件
├── apps/ # 模块化业务应用拆分
│ ├── user_account/ # 用户注册登录、实名认证、个人中心、权限管理模块
│ ├── goods_category/ # 商品分类管理、后台分类编辑模块
│ ├── goods_publish/ # 商品发布、图片上传、商品审核、上下架模块
│ ├── cart_favorite/ # 购物车管理、商品收藏、缓存同步模块
│ ├── order_trade/ # 订单创建、状态流转、交易确认模块
│ └── message_comment/ # 商品留言、双向交易评价、关键词过滤模块
├── core/ # 公共工具类文件夹
│ ├── goods_filter.py # 商品多条件筛选、搜索工具类
│ ├── sensitive_word.py # 文案、评价敏感词过滤工具
│ ├── pagination_tool.py # 全局通用分页封装工具
│ └── credit_score.py # 用户信用分加减分逻辑工具
├── static/ # 网站首页样式、图标、前端静态资源
├── templates/ # 前台所有页面HTML模板
├── media/ # 用户上传商品实拍图片存储目录
├── requirements.txt # 项目全部Python依赖包
└── readme.md # 项目部署、启动详细说明文档
2. 核心可运行代码片段
示例 1:商品核心数据模型(apps/goods_publish/models.py)
python
from django.db import models
from apps.user_account.models import User
from apps.goods_category.models import GoodsCategory
# 商品新旧程度枚举
NEW_LEVEL_CHOICE = (
("99新", "99新几乎全新"),
("95新", "95新轻微使用痕迹"),
("9成新", "9成新明显使用痕迹"),
("8成新及以下", "8成新及以下成色一般"),
)
# 商品审核状态枚举
AUDIT_STATUS_CHOICE = (
("wait", "待管理员审核"),
("pass", "审核通过已上架"),
("reject", "审核驳回未上架"),
)
# 商品上下架状态
SHELF_STATUS_CHOICE = (
("on", "在售上架"),
("off", "卖家自主下架"),
)
class GoodsInfo(models.Model):
"""闲置商品信息主表"""
goods_name = models.CharField(max_length=120, verbose_name="商品名称")
goods_desc = models.TextField(verbose_name="商品详细描述")
old_price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="商品原价")
sell_price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="售卖价格")
new_level = models.CharField(max_length=10, choices=NEW_LEVEL_CHOICE, verbose_name="新旧程度")
trade_address = models.CharField(max_length=60, verbose_name="校园交易地点")
goods_main_img = models.ImageField(upload_to="goods/main/", verbose_name="商品主图")
goods_category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name="所属分类")
seller = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="发布卖家")
audit_status = models.CharField(max_length=10, choices=AUDIT_STATUS_CHOICE, default="wait", verbose_name="审核状态")
shelf_status = models.CharField(max_length=10, choices=SHELF_STATUS_CHOICE, default="on", verbose_name="上下架状态")
view_count = models.IntegerField(default=0, verbose_name="商品浏览量")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="发布时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
class Meta:
verbose_name = "闲置商品信息"
verbose_name_plural = verbose_name
ordering = ["-create_time"]
def __str__(self):
return self.goods_name
示例 2:购物车 Redis 缓存同步核心逻辑(apps/cart_favorite/views.py)
python
import json
import redis
from django.conf import settings
from django.views import View
from django.http import JsonResponse
from apps.goods_publish.models import GoodsInfo
# 连接Redis购物车缓存库
redis_conn = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=2, decode_responses=True)
class CartAddView(View):
"""商品加入购物车视图逻辑"""
def post(self, request):
# 获取当前登录用户与商品ID
user = request.user
goods_id = request.POST.get("goods_id")
# 未登录用户禁止加入购物车
if not user.is_authenticated:
return JsonResponse({"code": 400, "msg": "请先登录校园账号!"})
# 校验商品是否存在且正常上架
try:
goods = GoodsInfo.objects.get(id=goods_id, audit_status="pass", shelf_status="on")
except GoodsInfo.DoesNotExist:
return JsonResponse({"code": 400, "msg": "商品不存在或已下架!"})
# 拼接购物车key:cart_用户id
cart_key = f"cart_{user.id}"
cart_data = redis_conn.hget(cart_key, goods_id)
# 判断商品是否已在购物车,存在则数量+1,不存在则新增
if cart_data:
cart_dict = json.loads(cart_data)
cart_dict["cart_num"] += 1
redis_conn.hset(cart_key, goods_id, json.dumps(cart_dict))
else:
new_cart_data = {
"goods_name": goods.goods_name,
"goods_img": str(goods.goods_main_img),
"sell_price": float(goods.sell_price),
"cart_num": 1
}
redis_conn.hset(cart_key, goods_id, json.dumps(new_cart_data))
return JsonResponse({"code": 200, "msg": "商品成功加入购物车"})
示例 3:交易完成后用户信用分更新工具类(core/credit_score.py)
python
from apps.user_account.models import User
class UserCreditTool:
"""用户信用分增减统一工具类"""
# 初始信用分
INIT_CREDIT = 100
# 单次加分分值
ADD_SCORE = 5
# 单次扣分分值
MINUS_SCORE = 10
@classmethod
def add_credit_score(cls, user_id):
"""交易履约完成,为双方增加信用分"""
user = User.objects.get(id=user_id)
user.credit_score += cls.ADD_SCORE
# 信用分上限固定120分
if user.credit_score > 120:
user.credit_score = 120
user.save()
return user.credit_score
@classmethod
def minus_credit_score(cls, user_id):
"""恶意放鸽子、违约,扣除信用分"""
user = User.objects.get(id=user_id)
user.credit_score -= cls.MINUS_SCORE
# 信用分最低不低于0
if user.credit_score < 0:
user.credit_score = 0
user.save()
return user.credit_score
@classmethod
def check_credit_limit(cls, user_id):
"""校验用户信用分是否低于阈值,低于则禁止发布商品"""
user = User.objects.get(id=user_id)
if user.credit_score < 40:
return False
return True
八、总结与展望
本篇博客聚焦垂直校园细分电商场景 ,基于原生 Django MVT 开发专属校园二手交易平台,区别于通用全品类商城系统,深度贴合高校线下面交、闲置物品流转的真实需求,和专栏过往异步聊天室、私有网盘、爬虫可视化、运维监控等所有项目技术方向、业务场景完全不重复。
项目完整覆盖用户实名认证、角色权限隔离、商品审核发布、Redis购物车缓存、订单状态流转、双向评价、信用分管控、敏感词过滤全套电商基础知识点,代码通俗易懂、业务逻辑贴近校园生活,非常适合课程设计、毕业设计以及简历实战项目,同时全程无复杂第三方依赖,本地一键即可运行调试。
后续迭代规划
- 新增站内私信聊天功能,买卖双方无需第三方软件即可线上一对一沟通;
- 新增商品求购专区,学生可发布求购需求,卖家主动匹配对接;
- 接入校园公告模块,平台发布交易防骗指南、校园交易安全提示;
- 新增订单超时自动关闭功能,未确认交易72小时后自动关闭订单释放商品。