校园二手交易平台开发:Django+Wepy技术选型与实战
发布时间:2026/9/29 18:31:00来源:尧图网络
简介这份资源是依托Python、Django与Wepy框架构建的校园二手交易平台微信小程序毕业设计资料包含论文与完整代码适合对多技术栈感兴趣的学习者可用于毕业设计、课程实践、实训项目或创业原型搭建。后端基于Django的MTV结构处理业务逻辑数据库采用MySQL前端在Node.js环境下用Wepy框架完成页面构建与功能测试主要模块涵盖用户注册与资料完善、商品发布与查看、评论、点赞与收藏等互动功能。压缩包共181个文件约3.66MB以39个py源码、29个wpy页面组件、20个js脚本为主另含pyc编译文件、zbak备份、png图片、json配置及docx说明文档目录结构清晰便于按模块阅读与调试。目前已有40人学习。读者可借此理解Django与Wepy的协作方式掌握小程序端页面组织与接口调用思路并参考运行说明书完成环境搭建与代码调试为二次开发或功能扩展提供可借鉴的实践样本。1. 校园二手交易平台为什么用 Django Wepy 而不是 SpringBoot 或若依每年毕业季宿舍楼下堆成山的二手书、小风扇、自行车最后大多进了废品站。学生想卖找不到人想买不知道谁在卖。校园二手交易平台要解决的就是这个信息撮合问题——把发布、搜索、下单、沟通这条链路跑通让同一所学校里的供需对上。技术选型上后端我选 Python 的 Django前端小程序用 Wepy 框架。为什么不用热搜里常见的 SpringBoot 或若依框架因为校园项目的特点是开发人手少、迭代快、预算低。Django 自带 ORM、Admin 后台、用户认证和迁移工具一个后端能顶三个人用若依那套前后端分离方案更适合企业级中后台对小程序场景偏重。Wepy 是早期的小程序组件化框架语法接近 Vue对熟悉前端但没写过原生小程序的开发者友好编译产物就是标准小程序代码不引入额外运行时。这套组合适合谁适合在校学生做课程设计或毕业设计也适合想快速验证校园二手业务的小团队。它不追求高并发追求的是两周内能跑起来、能演示、能真实用。下面从环境搭建到核心功能再到部署踩坑一步步拆开讲。2. 环境搭建与项目骨架从 python 安装到 Django 跑起来2.1 后端环境python 安装与虚拟环境隔离很多人卡在第一步不是代码写错而是 python 安装和包管理混乱。Windows 上建议从 python 官网下载 3.10 或 3.11 版本安装时勾选“Add Python to PATH”。Linux 系统安装 python 通常自带 3.8 以上但 pip 可能需要单独装。装完后用python --version和pip --version确认。虚拟环境是必须的否则 Django 版本冲突会让你怀疑人生。我一般用 venv不推荐全局装包。# 创建项目目录并进入 mkdir campus_market cd campus_market # 创建虚拟环境Windows 用 python -m venv venv python3 -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate source venv/bin/activate # 安装 Django 和数据库驱动 pip install django4.2 mysqlclient pillow这里选 Django 4.2 是因为它是 LTS 版本官方维护到 2026 年校园项目用两年足够。mysqlclient是 MySQL 驱动pillow用于处理商品图片上传。如果你用 SQLite 做开发可以暂时不装 mysqlclient但上线前一定要换 MySQLSQLite 的并发写入在多人同时发布商品时会锁表。提示pip 安装慢的话换国内镜像源命令后面加-i https://pypi.tuna.tsinghua.edu.cn/simple这是常规操作不涉及任何网络工具。2.2 创建 Django 项目与核心 App 划分一个校园二手平台至少需要用户、商品、订单、消息四个模块。Django 的 App 划分要按业务边界来不要把所有模型塞进一个 App。# 创建 Django 项目 django-admin startproject campus_market . # 创建四个核心 App python manage.py startapp users python manage.py startapp goods python manage.py startapp orders python manage.py startapp chat创建完后在settings.py的INSTALLED_APPS里注册这四个 App。数据库配置改成 MySQL# settings.py 数据库配置片段 DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: campus_market, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: {charset: utf8mb4}, } }utf8mb4是为了支持 emoji 和生僻字学生发布商品时经常在描述里加表情用utf8会报错。HOST和PORT按实际数据库地址改本地开发就是 127.0.0.1。2.3 Wepy 前端环境小程序项目初始化Wepy 的安装依赖 Node.js建议用 14.x 或 16.x 版本太高版本编译会报错。先全局安装 wepy-clinpm install wepy-cli -g # 初始化项目选择空模板 wepy init standard campus-market-wepy cd campus-market-wepy npm installWepy 项目结构里src/pages放页面src/components放组件src/api放请求封装。编译命令是wepy build --watch产物在dist目录用微信开发者工具打开dist即可预览。前后端联调时Django 跑在127.0.0.1:8000Wepy 请求这个地址。微信开发者工具需要勾选“不校验合法域名”否则本地请求会被拦截。上线时再把域名换成备案过的 HTTPS 域名。3. 核心数据模型与接口商品发布、搜索、下单怎么落地3.1 商品模型设计字段、索引与图片存储商品表是平台的核心字段设计直接影响搜索和列表性能。我一般这样定义# goods/models.py from django.db import models from users.models import User class Category(models.Model): name models.CharField(max_length32, uniqueTrue) sort_order models.IntegerField(default0) class Meta: ordering [sort_order] class Goods(models.Model): STATUS_CHOICES ( (0, 在售), (1, 已售), (2, 下架), ) title models.CharField(max_length64, db_indexTrue) description models.TextField(max_length1000) price models.DecimalField(max_digits8, decimal_places2) original_price models.DecimalField(max_digits8, decimal_places2, nullTrue, blankTrue) category models.ForeignKey(Category, on_deletemodels.SET_NULL, nullTrue) seller models.ForeignKey(User, on_deletemodels.CASCADE, related_namegoods_list) status models.SmallIntegerField(choicesSTATUS_CHOICES, default0, db_indexTrue) cover_image models.ImageField(upload_togoods/%Y%m/) view_count models.IntegerField(default0) created_at models.DateTimeField(auto_now_addTrue, db_indexTrue) class Meta: ordering [-created_at] indexes [ models.Index(fields[status, -created_at]), models.Index(fields[category, status]), ]title加db_indexTrue是为了搜索时走索引但注意 MySQL 的 like %关键词% 不会走索引后面会讲怎么优化。status和created_at的联合索引覆盖了“在售商品按时间倒序”这个最高频查询。cover_image用upload_to按年月分目录避免单目录文件过多导致 inode 性能下降。图片上传前要在 Wepy 端压缩学生用手机拍的照片动辄 3-5MB直接传会导致接口超时。Wepy 里可以用wx.compressImage压缩到 200KB 以内再上传。3.2 商品发布与列表接口Django REST 写法接口用 Django 的JsonResponse或 DRF 都行校园项目为了少装依赖我直接用原生视图加csrf_exempt装饰器。发布接口# goods/views.py import json from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.core.paginator import Paginator from .models import Goods, Category csrf_exempt def publish_goods(request): if request.method ! POST: return JsonResponse({code: 405, msg: 方法不允许}) try: data request.POST title data.get(title, ).strip() price data.get(price, 0) if not title or len(title) 2: return JsonResponse({code: 400, msg: 标题至少2个字}) if float(price) 0: return JsonResponse({code: 400, msg: 价格必须大于0}) goods Goods.objects.create( titletitle, descriptiondata.get(description, ), priceprice, category_iddata.get(category_id), seller_idrequest.session.get(user_id), cover_imagerequest.FILES.get(cover), ) return JsonResponse({code: 0, msg: 发布成功, id: goods.id}) except Exception as e: return JsonResponse({code: 500, msg: str(e)})这里用request.session取用户 ID前提是登录接口已经把用户信息写进 session。Wepy 端请求时带上 cookieDjango 的 session 才能识别。如果前后端域名不同需要配置CORS和credentials这是常见翻车点。列表接口带分页和筛选def goods_list(request): page int(request.GET.get(page, 1)) category_id request.GET.get(category_id) keyword request.GET.get(keyword, ).strip() qs Goods.objects.filter(status0).select_related(seller, category) if category_id: qs qs.filter(category_idcategory_id) if keyword: qs qs.filter(title__icontainskeyword) paginator Paginator(qs, 10) page_obj paginator.get_page(page) data [{ id: g.id, title: g.title, price: str(g.price), cover: g.cover_image.url if g.cover_image else , seller: g.seller.nickname, created_at: g.created_at.strftime(%m-%d %H:%M), } for g in page_obj] return JsonResponse({code: 0, data: data, total: paginator.count})select_related是关键优化不加的话每取一个商品都要查一次卖家和分类10 条数据就是 20 次额外查询。icontains对应 SQL 的like %关键词%数据量超过 5000 条后明显变慢后面进阶部分讲替代方案。3.3 Wepy 端请求封装与页面调用Wepy 的请求不要在每个页面里写wx.request统一封装成api.js// src/api/index.js import wepy from wepy const BASE_URL http://127.0.0.1:8000 export function request(url, method GET, data {}) { return new Promise((resolve, reject) { wepy.request({ url: BASE_URL url, method: method, data: data, header: { content-type: application/json }, success: res { if (res.data.code 0) { resolve(res.data) } else { wepy.showToast({ title: res.data.msg, icon: none }) reject(res.data) } }, fail: err { wepy.showToast({ title: 网络异常, icon: none }) reject(err) } }) }) } export function getGoodsList(page, categoryId, keyword) { return request(/goods/list, GET, { page, category_id: categoryId, keyword }) }页面里调用import { getGoodsList } from ../api/index export default class Home extends wepy.page { data { list: [], page: 1, hasMore: true } methods { async loadGoods() { const res await getGoodsList(this.page, this.categoryId, this.keyword) this.list this.list.concat(res.data) this.hasMore this.list.length res.total this.$apply() } } }Wepy 的$apply()是手动触发视图更新忘记写会导致数据变了但页面不刷新这是新手最常见的坑。请求封装里统一处理了code ! 0的提示页面只需要关心成功逻辑。4. 避坑与排查校园二手平台开发中最容易翻车的 5 个点4.1 图片上传后前端显示 404现象商品发布成功但列表页图片是裂图控制台报 404。原因Django 开发模式下MEDIA_URL没有配置路由上传的文件无法通过 URL 访问。解决在settings.py加MEDIA_URL /media/和MEDIA_ROOT os.path.join(BASE_DIR, media)在urls.py加from django.conf import settings from django.conf.urls.static import static urlpatterns [ # ... 其他路由 ] static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)注意static()只在DEBUGTrue时生效上线后要用 Nginx 托管 media 目录。4.2 Wepy 编译后页面空白控制台无报错现象wepy build --watch显示编译成功但微信开发者工具打开是白屏。原因Wepy 的app.wpy里config配置的pages路径和实际文件不匹配或者dist目录没有重新生成。解决检查src/app.wpy的pages数组路径不带.wpy后缀删除dist目录重新编译确认微信开发者工具打开的是dist目录而不是项目根目录。4.3 登录状态丢失每次请求都提示未登录现象登录接口返回成功但后续请求 session 取不到用户。原因Wepy 的wepy.request默认不带 cookieDjango 的 session 依赖 cookie。解决在请求封装里加withCredentials: true同时 Django 端配置CORS_ALLOW_CREDENTIALS True和SESSION_COOKIE_SAMESITE None。如果不用 CORS 库就在响应头手动加Access-Control-Allow-Credentials: true。4.4 商品列表分页重复或漏数据现象翻到第二页时出现第一页的商品或者某些商品永远不出现。原因排序字段created_at有相同值MySQL 分页时顺序不稳定。解决在Meta.ordering里加一个唯一字段兜底比如[-created_at, -id]。这样即使时间相同也有确定的顺序。4.5 并发下单导致同一商品被卖两次现象两个用户同时点“立即购买”都生成了订单。原因下单接口没有做库存或状态校验的原子操作。解决用select_for_update锁行或者用条件更新updated Goods.objects.filter(idgoods_id, status0).update(status1) if not updated: return JsonResponse({code: 400, msg: 商品已被抢走})filter(status0).update(status1)是原子操作返回受影响行数0 表示已经被别人改过。这比先查再改可靠得多。5. 进阶技巧用 Django 的 Q 对象和 Wepy 的 mixin 提升开发效率5.1 复杂搜索用 Q 对象替代 icontains 拼接校园二手平台经常需要“标题或描述包含关键词”的搜索。用Q对象可以组合条件避免多次查询from django.db.models import Q def search_goods(request): keyword request.GET.get(keyword, ).strip() qs Goods.objects.filter(status0) if keyword: qs qs.filter( Q(title__icontainskeyword) | Q(description__icontainskeyword) ).distinct() # 后续分页逻辑Q(title__icontainskeyword) | Q(description__icontainskeyword)生成WHERE title LIKE %kw% OR description LIKE %kw%distinct()去重。数据量超过 1 万条时icontains会全表扫描这时候可以加一个search_keywords字段发布时把标题和描述的分词结果存进去搜索时用search_keywords__contains走索引。这是用空间换时间的常规做法。5.2 Wepy mixin 复用登录校验和分页逻辑Wepy 支持 mixin可以把“检查登录”和“上拉加载更多”抽出来复用// src/mixins/pagination.js import wepy from wepy export default class PaginationMixin extends wepy.mixin { data { page: 1, hasMore: true, loading: false } methods { async loadMore(fetchFn) { if (!this.hasMore || this.loading) return this.loading true const res await fetchFn(this.page) this.list this.list.concat(res.data) this.hasMore this.list.length res.total this.page 1 this.loading false this.$apply() } } }页面里mixins [PaginationMixin]然后调用this.loadMore(getGoodsList)即可。这样每个列表页少写 20 行重复代码也避免了忘记重置loading导致上拉失效。5.3 用 Django Admin 做运营后台省掉一套管理界面Django 自带 Admin 是校园项目最大的福利。注册模型后运营同学可以直接在后台改商品状态、审核用户# goods/admin.py from django.contrib import admin from .models import Goods, Category admin.register(Goods) class GoodsAdmin(admin.ModelAdmin): list_display (id, title, price, seller, status, created_at) list_filter (status, category) search_fields (title, seller__nickname) list_editable (status,) actions [mark_sold] def mark_sold(self, request, queryset): queryset.update(status1) mark_sold.short_description 批量标记为已售list_editable让状态可以直接在列表页改actions加批量操作。这样不用单独写管理后台省下的时间可以打磨小程序端的体验。5.4 验证方法用 pytest 跑通核心接口热搜里 pytest 框架出现频率很高校园项目也值得加。装pytest-django后写测试# goods/tests.py import pytest from django.test import Client from goods.models import Goods, Category pytest.mark.django_db def test_publish_goods(): client Client() category Category.objects.create(name教材) response client.post(/goods/publish, { title: 高等数学教材, price: 15.00, category_id: category.id, }) assert response.json()[code] 0 assert Goods.objects.count() 1跑pytest就能验证发布接口是否正常。测试数据库是独立的不会污染开发数据。我一般把发布、搜索、下单三个接口的测试写全改代码后跑一遍比手动点页面快得多。这套 Django Wepy 的组合我从环境搭建到接口联调大概用了三天其中一天半在踩图片上传和 session 的坑。如果你也在做校园二手平台建议先把用户和商品两个模块跑通再补订单和聊天。不要一上来就追求功能全能发布、能搜到、能联系卖家这个平台就有人用。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网