1. 项目背景与核心需求
这个Python+微信小程序的课程教学作业笔记平台,源于我在高校担任助教时的实际痛点。每次收作业时,学生交上来的文件格式五花八门——有Word、PDF、甚至手机拍照的图片,批改后反馈周期长,师生互动效率低下。市面上现有的教学平台要么功能臃肿,要么缺乏针对课程教学的轻量化工具。
经过三个月的需求调研(覆盖12个班级的师生),我们确定了几个核心需求场景:
- 学生需要能随时随地上传多格式作业(代码、文档、图片)
- 教师要求结构化批注功能(特别是对编程作业的代码片段点评)
- 双方都需要实时通知和版本追踪
- 数据必须支持导出备份
2. 技术架构设计
2.1 微信小程序端关键技术点
选择微信小程序而非H5的主要考虑是其原生体验和微信生态优势。在开发中重点解决了几个典型问题:
页面布局方案:
<!-- 作业提交页核心结构 --> <view class="container"> <uploader files="{{files}}" max-count="5" bind:success="onUploadSuccess" custom-class="upload-area" /> <editor placeholder="添加作业说明..." bind:input="onEditorInput" show-confirm-bar="{{false}}" /> </view>特别注意:微信小程序editor组件在安卓机上的兼容性问题,需要额外处理键盘弹起时的页面滚动
文件上传优化:
- 采用分片上传策略(每片1MB)
- 前端计算文件MD5实现秒传
- 图片文件自动压缩(使用wx.compressImage API)
2.2 Python后端技术栈
选用Django而非Flask的主要考量是其完善的Admin系统和ORM支持。关键配置示例:
# settings.py 关键配置 COS_CONFIG = { 'Bucket': 'edu-platform-125000000', 'Region': 'ap-shanghai', 'SecretId': os.getenv('COS_SECRET_ID'), 'SecretKey': os.getenv('COS_SECRET_KEY'), 'Token': None, 'Scheme': 'https' } # 文件上传签名生成 def get_upload_signature(request): from qcloud_cos import CosConfig, CosS3Client config = CosConfig(**COS_CONFIG) client = CosS3Client(config) return JsonResponse(client.get_auth( Method='PUT', Key=f"uploads/{uuid4().hex}" ))2.3 实时通信方案对比
我们测试了三种方案后最终选择:
- WebSocket:原生支持但微信小程序后台存活限制严格
- 云开发数据库监听:成本高且存在并发限制
- 最终方案:定时轮询+长连接降级
// 小程序端消息检查逻辑 function checkNewMessages() { const now = Date.now() if (now - lastCheckTime > 30000) { // 30秒常规轮询 return request('/api/messages/check') } else if (navigator.onLine) { return maintainConnection() // 保持长连接 } }3. 核心功能实现细节
3.1 作业批注系统
教师端实现的核心交互逻辑:
# views.py class AnnotationViewSet(ModelViewSet): @action(detail=True, methods=['POST']) def add_marker(self, request, pk=None): from PyPDF2 import PdfFileWriter, PdfFileReader import fitz # PyMuPDF # 解析坐标数据 coord_x = request.data.get('x') coord_y = request.data.get('y') page_num = request.data.get('page') # PDF批注处理 if submission.file_type == 'pdf': doc = fitz.open(submission.file.path) page = doc[page_num] annot = page.addTextAnnot( point=(coord_x, coord_y), text=request.data['comment'] ) doc.saveIncr()踩坑记录:PyPDF2对中文支持较差,最终改用PyMuPDF实现
3.2 代码作业的特殊处理
针对编程作业的特点,我们增加了:
- 代码差异对比(使用difflib)
- 语法高亮渲染
- 自动PEP8检查
# utils/code_analysis.py def check_pep8(code): import pycodestyle from io import StringIO f = StringIO(code) checker = pycodestyle.Checker( lines=f.readlines(), show_source=True ) return { 'error_count': checker.check_all(), 'messages': checker.report.get_messages() }4. 性能优化实战
4.1 数据库查询优化
典型N+1查询问题解决方案:
# 优化前 submissions = Submission.objects.filter(course_id=1) for sub in submissions: # 每次循环都查询数据库 print(sub.student.name) # 优化后 submissions = Submission.objects.select_related( 'student' ).prefetch_related( 'annotations' ).filter(course_id=1)4.2 缓存策略设计
采用三级缓存架构:
- 热点数据:Redis缓存(如课程公告)
- 复杂计算:Memcached(如成绩统计)
- CDN加速:静态资源(作业附件)
缓存失效策略特别重要:
# decorators.py def cache_by_course(func): @wraps(func) def wrapper(request, course_id): cache_key = f'course_{course_id}_{func.__name__}' data = cache.get(cache_key) if not data: data = func(request, course_id) cache.set(cache_key, data, timeout=3600) return data return wrapper5. 安全防护措施
5.1 文件上传安全
实现的安全检查流程:
- 文件头校验(非扩展名校验)
- 病毒扫描(调用腾讯云API)
- 内容安全检查(敏感词过滤)
ALLOWED_MAGIC_NUMBERS = { 'PDF': b'%PDF-', 'ZIP': b'PK\x03\x04', 'PNG': b'\x89PNG', } def validate_file_header(uploaded_file): header = uploaded_file.read(8) uploaded_file.seek(0) for _, magic in ALLOWED_MAGIC_NUMBERS.items(): if header.startswith(magic): return True return False5.2 微信登录安全加固
除官方unionid机制外,我们额外增加:
- 登录态二次验证
- 设备指纹识别
- 异常行为检测(如频繁切换账号)
// 小程序端安全增强 function enhancedLogin() { wx.login({ success: res => { const deviceInfo = wx.getSystemInfoSync() wx.request({ url: '/api/auth/login', data: { code: res.code, deviceId: deviceInfo.system + deviceInfo.platform, screenWidth: deviceInfo.screenWidth } }) } }) }6. 部署与监控方案
6.1 Docker化部署
生产环境Dockerfile关键配置:
FROM python:3.8-slim RUN apt-get update && apt-get install -y \ libmagic1 \ # 文件类型检测依赖 poppler-utils # PDF处理 COPY requirements.txt . RUN pip install -r requirements.txt --no-cache-dir \ && rm -rf /root/.cache/pip ENV PYTHONUNBUFFERED 1 EXPOSE 8000 CMD ["gunicorn", "-w 4", "-b :8000", "core.wsgi"]6.2 监控告警配置
使用Prometheus+Granfana监控以下指标:
- 小程序API响应时间P99
- 文件上传成功率
- 数据库连接池使用率
对应的告警规则示例:
groups: - name: api.rules rules: - alert: HighLatency expr: histogram_quantile(0.99, sum(rate(django_http_response_seconds_bucket[1m])) by (le)) > 3 for: 5m labels: severity: critical annotations: summary: "高延迟请求 {{ $value }}s"7. 实际运行数据
上线6个月后的关键指标:
- 日均活跃用户:1200+
- 平均作业提交时间:从3天缩短至1.2天
- 教师批改效率提升:40%
- 服务器负载:2核4G容器 ×3(峰值CPU<60%)
遇到的典型问题及解决方案:
- 微信iOS版本兼容性问题:某些API在iOS端表现不一致,通过条件编译解决
- PDF批注坐标偏移:不同设备DPI差异导致,增加设备像素比校准
- 高并发提交时的锁竞争:改用SELECT FOR UPDATE SKIP LOCKED
这个项目给我的深刻体会是:教育类工具开发必须同时考虑技术实现和教学场景的特殊性。比如在代码作业评审时,简单的行号引用可能因为学生后续修改而错位,我们最终采用代码指纹(AST hash)来持久化定位批注位置。